mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Auto merge of #17618 - Veykril:rustc_skip_during_method_dispatch, r=Veykril
Support rustc_skip_during_method_dispatch Fixes https://github.com/rust-lang/rust-analyzer/issues/17256
This commit is contained in:
commit
a62ea0a59e
5 changed files with 94 additions and 17 deletions
|
@ -223,6 +223,7 @@ pub struct TraitData {
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
pub rustc_has_incoherent_inherent_impls: bool,
|
pub rustc_has_incoherent_inherent_impls: bool,
|
||||||
pub skip_array_during_method_dispatch: bool,
|
pub skip_array_during_method_dispatch: bool,
|
||||||
|
pub skip_boxed_slice_during_method_dispatch: bool,
|
||||||
pub fundamental: bool,
|
pub fundamental: bool,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
/// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
|
/// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
|
||||||
|
@ -250,8 +251,17 @@ impl TraitData {
|
||||||
let is_unsafe = tr_def.is_unsafe;
|
let is_unsafe = tr_def.is_unsafe;
|
||||||
let visibility = item_tree[tr_def.visibility].clone();
|
let visibility = item_tree[tr_def.visibility].clone();
|
||||||
let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
|
let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
|
||||||
let skip_array_during_method_dispatch =
|
let mut skip_array_during_method_dispatch =
|
||||||
attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
|
attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
|
||||||
|
let mut skip_boxed_slice_during_method_dispatch = false;
|
||||||
|
for tt in attrs.by_key(&sym::rustc_skip_during_method_dispatch).tt_values() {
|
||||||
|
for tt in tt.token_trees.iter() {
|
||||||
|
if let crate::tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt {
|
||||||
|
skip_array_during_method_dispatch |= ident.sym == sym::array;
|
||||||
|
skip_boxed_slice_during_method_dispatch |= ident.sym == sym::boxed_slice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let rustc_has_incoherent_inherent_impls =
|
let rustc_has_incoherent_inherent_impls =
|
||||||
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
|
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
|
||||||
let fundamental = attrs.by_key(&sym::fundamental).exists();
|
let fundamental = attrs.by_key(&sym::fundamental).exists();
|
||||||
|
@ -269,6 +279,7 @@ impl TraitData {
|
||||||
is_unsafe,
|
is_unsafe,
|
||||||
visibility,
|
visibility,
|
||||||
skip_array_during_method_dispatch,
|
skip_array_during_method_dispatch,
|
||||||
|
skip_boxed_slice_during_method_dispatch,
|
||||||
rustc_has_incoherent_inherent_impls,
|
rustc_has_incoherent_inherent_impls,
|
||||||
fundamental,
|
fundamental,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
|
use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::{adt::StructFlags, ImplData},
|
data::{adt::StructFlags, ImplData},
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
|
@ -16,7 +16,6 @@ use hir_expand::name::Name;
|
||||||
use intern::sym;
|
use intern::sym;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use span::Edition;
|
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
@ -25,12 +24,14 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
error_lifetime, from_chalk_trait_id, from_foreign_def_id,
|
error_lifetime, from_chalk_trait_id, from_foreign_def_id,
|
||||||
infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast},
|
infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast},
|
||||||
|
lang_items::is_box,
|
||||||
primitive::{FloatTy, IntTy, UintTy},
|
primitive::{FloatTy, IntTy, UintTy},
|
||||||
to_chalk_trait_id,
|
to_chalk_trait_id,
|
||||||
utils::all_super_traits,
|
utils::all_super_traits,
|
||||||
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, Goal, Guidance,
|
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
|
||||||
InEnvironment, Interner, Scalar, Solution, Substitution, TraitEnvironment, TraitRef,
|
Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution,
|
||||||
TraitRefExt, Ty, TyBuilder, TyExt,
|
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind,
|
||||||
|
WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is used as a key for indexing impls.
|
/// This is used as a key for indexing impls.
|
||||||
|
@ -1146,17 +1147,30 @@ fn iterate_trait_method_candidates(
|
||||||
'traits: for &t in traits_in_scope {
|
'traits: for &t in traits_in_scope {
|
||||||
let data = db.trait_data(t);
|
let data = db.trait_data(t);
|
||||||
|
|
||||||
// Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during
|
// Traits annotated with `#[rustc_skip_during_method_dispatch]` are skipped during
|
||||||
// method resolution, if the receiver is an array, and we're compiling for editions before
|
// method resolution, if the receiver is an array, and we're compiling for editions before
|
||||||
// 2021.
|
// 2021.
|
||||||
// This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
|
// This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
|
||||||
// arrays.
|
// arrays.
|
||||||
if data.skip_array_during_method_dispatch
|
if data.skip_array_during_method_dispatch
|
||||||
&& matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..))
|
&& matches!(self_ty.kind(Interner), TyKind::Array(..))
|
||||||
{
|
{
|
||||||
// FIXME: this should really be using the edition of the method name's span, in case it
|
// FIXME: this should really be using the edition of the method name's span, in case it
|
||||||
// comes from a macro
|
// comes from a macro
|
||||||
if db.crate_graph()[krate].edition < Edition::Edition2021 {
|
if !db.crate_graph()[krate].edition.at_least_2021() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if data.skip_boxed_slice_during_method_dispatch
|
||||||
|
&& matches!(
|
||||||
|
self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst)
|
||||||
|
if is_box(table.db, *def)
|
||||||
|
&& matches!(subst.at(Interner, 0).assert_ty_ref(Interner).kind(Interner), TyKind::Slice(..))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// FIXME: this should really be using the edition of the method name's span, in case it
|
||||||
|
// comes from a macro
|
||||||
|
if !db.crate_graph()[krate].edition.at_least_2024() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1619,15 +1633,11 @@ fn generic_implements_goal(
|
||||||
let kinds =
|
let kinds =
|
||||||
binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
|
binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
|
||||||
let vk = match it.data(Interner) {
|
let vk = match it.data(Interner) {
|
||||||
chalk_ir::GenericArgData::Ty(_) => {
|
GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
|
GenericArgData::Lifetime(_) => VariableKind::Lifetime,
|
||||||
}
|
GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()),
|
||||||
chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
|
|
||||||
chalk_ir::GenericArgData::Const(c) => {
|
|
||||||
chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
|
WithKind::new(vk, UniverseIndex::ROOT)
|
||||||
}));
|
}));
|
||||||
let binders = CanonicalVarKinds::from_iter(Interner, kinds);
|
let binders = CanonicalVarKinds::from_iter(Interner, kinds);
|
||||||
|
|
||||||
|
|
|
@ -1640,6 +1640,55 @@ impl<'a, T> IntoIterator for &'a [T] {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_during_method_dispatch() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
//- /main2018.rs crate:main2018 deps:core edition:2018
|
||||||
|
use core::IntoIterator;
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
let v = [4].into_iter();
|
||||||
|
v;
|
||||||
|
//^ &'? i32
|
||||||
|
|
||||||
|
let a = [0, 1].into_iter();
|
||||||
|
a;
|
||||||
|
//^ &'? i32
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /main2021.rs crate:main2021 deps:core edition:2021
|
||||||
|
use core::IntoIterator;
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
let v = [4].into_iter();
|
||||||
|
v;
|
||||||
|
//^ i32
|
||||||
|
|
||||||
|
let a = [0, 1].into_iter();
|
||||||
|
a;
|
||||||
|
//^ &'? i32
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /core.rs crate:core
|
||||||
|
#[rustc_skip_during_method_dispatch(array, boxed_slice)]
|
||||||
|
pub trait IntoIterator {
|
||||||
|
type Out;
|
||||||
|
fn into_iter(self) -> Self::Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IntoIterator for [T; 1] {
|
||||||
|
type Out = T;
|
||||||
|
fn into_iter(self) -> Self::Out { loop {} }
|
||||||
|
}
|
||||||
|
impl<'a, T> IntoIterator for &'a [T] {
|
||||||
|
type Out = &'a T;
|
||||||
|
fn into_iter(self) -> Self::Out { loop {} }
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sized_blanket_impl() {
|
fn sized_blanket_impl() {
|
||||||
check_infer(
|
check_infer(
|
||||||
|
|
|
@ -400,6 +400,7 @@ define_symbols! {
|
||||||
rustc_reservation_impl,
|
rustc_reservation_impl,
|
||||||
rustc_safe_intrinsic,
|
rustc_safe_intrinsic,
|
||||||
rustc_skip_array_during_method_dispatch,
|
rustc_skip_array_during_method_dispatch,
|
||||||
|
rustc_skip_during_method_dispatch,
|
||||||
semitransparent,
|
semitransparent,
|
||||||
shl_assign,
|
shl_assign,
|
||||||
shl,
|
shl,
|
||||||
|
@ -455,4 +456,6 @@ define_symbols! {
|
||||||
vectorcall,
|
vectorcall,
|
||||||
wasm,
|
wasm,
|
||||||
win64,
|
win64,
|
||||||
|
array,
|
||||||
|
boxed_slice,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ impl Edition {
|
||||||
self >= Edition::Edition2024
|
self >= Edition::Edition2024
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn at_least_2021(self) -> bool {
|
||||||
|
self >= Edition::Edition2021
|
||||||
|
}
|
||||||
|
|
||||||
pub fn at_least_2018(self) -> bool {
|
pub fn at_least_2018(self) -> bool {
|
||||||
self >= Edition::Edition2018
|
self >= Edition::Edition2018
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue