mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-15 06:33:58 +00:00
Support rustc_has_incoherent_inherent_impls
This commit is contained in:
parent
957b4bb216
commit
ca1389ef9f
6 changed files with 153 additions and 37 deletions
|
@ -36,6 +36,7 @@ pub struct StructData {
|
||||||
pub variant_data: Arc<VariantData>,
|
pub variant_data: Arc<VariantData>,
|
||||||
pub repr: Option<ReprData>,
|
pub repr: Option<ReprData>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
|
pub rustc_has_incoherent_inherent_impls: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -44,6 +45,7 @@ pub struct EnumData {
|
||||||
pub variants: Arena<EnumVariantData>,
|
pub variants: Arena<EnumVariantData>,
|
||||||
pub repr: Option<ReprData>,
|
pub repr: Option<ReprData>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
|
pub rustc_has_incoherent_inherent_impls: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -157,6 +159,10 @@ impl StructData {
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||||
|
let rustc_has_incoherent_inherent_impls = item_tree
|
||||||
|
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||||
|
.by_key("rustc_has_incoherent_inherent_impls")
|
||||||
|
.exists();
|
||||||
|
|
||||||
let strukt = &item_tree[loc.id.value];
|
let strukt = &item_tree[loc.id.value];
|
||||||
let (variant_data, diagnostics) = lower_fields(
|
let (variant_data, diagnostics) = lower_fields(
|
||||||
|
@ -175,6 +181,7 @@ impl StructData {
|
||||||
variant_data: Arc::new(variant_data),
|
variant_data: Arc::new(variant_data),
|
||||||
repr,
|
repr,
|
||||||
visibility: item_tree[strukt.visibility].clone(),
|
visibility: item_tree[strukt.visibility].clone(),
|
||||||
|
rustc_has_incoherent_inherent_impls,
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
@ -194,6 +201,11 @@ impl StructData {
|
||||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||||
|
|
||||||
|
let rustc_has_incoherent_inherent_impls = item_tree
|
||||||
|
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||||
|
.by_key("rustc_has_incoherent_inherent_impls")
|
||||||
|
.exists();
|
||||||
|
|
||||||
let union = &item_tree[loc.id.value];
|
let union = &item_tree[loc.id.value];
|
||||||
let (variant_data, diagnostics) = lower_fields(
|
let (variant_data, diagnostics) = lower_fields(
|
||||||
db,
|
db,
|
||||||
|
@ -211,6 +223,7 @@ impl StructData {
|
||||||
variant_data: Arc::new(variant_data),
|
variant_data: Arc::new(variant_data),
|
||||||
repr,
|
repr,
|
||||||
visibility: item_tree[union.visibility].clone(),
|
visibility: item_tree[union.visibility].clone(),
|
||||||
|
rustc_has_incoherent_inherent_impls,
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
@ -231,6 +244,10 @@ impl EnumData {
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
|
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
|
||||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||||
|
let rustc_has_incoherent_inherent_impls = item_tree
|
||||||
|
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||||
|
.by_key("rustc_has_incoherent_inherent_impls")
|
||||||
|
.exists();
|
||||||
|
|
||||||
let enum_ = &item_tree[loc.id.value];
|
let enum_ = &item_tree[loc.id.value];
|
||||||
let mut variants = Arena::new();
|
let mut variants = Arena::new();
|
||||||
|
@ -271,6 +288,7 @@ impl EnumData {
|
||||||
variants,
|
variants,
|
||||||
repr,
|
repr,
|
||||||
visibility: item_tree[enum_.visibility].clone(),
|
visibility: item_tree[enum_.visibility].clone(),
|
||||||
|
rustc_has_incoherent_inherent_impls,
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -168,6 +168,7 @@ pub struct TypeAliasData {
|
||||||
pub type_ref: Option<Interned<TypeRef>>,
|
pub type_ref: Option<Interned<TypeRef>>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
|
pub rustc_has_incoherent_inherent_impls: bool,
|
||||||
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
|
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
|
||||||
pub bounds: Vec<Interned<TypeBound>>,
|
pub bounds: Vec<Interned<TypeBound>>,
|
||||||
}
|
}
|
||||||
|
@ -186,11 +187,17 @@ impl TypeAliasData {
|
||||||
item_tree[typ.visibility].clone()
|
item_tree[typ.visibility].clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let rustc_has_incoherent_inherent_impls = item_tree
|
||||||
|
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
|
||||||
|
.by_key("rustc_has_incoherent_inherent_impls")
|
||||||
|
.exists();
|
||||||
|
|
||||||
Arc::new(TypeAliasData {
|
Arc::new(TypeAliasData {
|
||||||
name: typ.name.clone(),
|
name: typ.name.clone(),
|
||||||
type_ref: typ.type_ref.clone(),
|
type_ref: typ.type_ref.clone(),
|
||||||
visibility,
|
visibility,
|
||||||
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
||||||
|
rustc_has_incoherent_inherent_impls,
|
||||||
bounds: typ.bounds.to_vec(),
|
bounds: typ.bounds.to_vec(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -202,6 +209,7 @@ pub struct TraitData {
|
||||||
pub items: Vec<(Name, AssocItemId)>,
|
pub items: Vec<(Name, AssocItemId)>,
|
||||||
pub is_auto: bool,
|
pub is_auto: bool,
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
|
pub rustc_has_incoherent_inherent_impls: 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
|
||||||
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
||||||
|
@ -231,11 +239,11 @@ impl TraitData {
|
||||||
let is_auto = tr_def.is_auto;
|
let is_auto = tr_def.is_auto;
|
||||||
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 skip_array_during_method_dispatch = item_tree
|
let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
|
||||||
.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into())
|
let skip_array_during_method_dispatch =
|
||||||
.by_key("rustc_skip_array_during_method_dispatch")
|
attrs.by_key("rustc_skip_array_during_method_dispatch").exists();
|
||||||
.exists();
|
let rustc_has_incoherent_inherent_impls =
|
||||||
|
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
||||||
let (items, attribute_calls, diagnostics) = match &tr_def.items {
|
let (items, attribute_calls, diagnostics) = match &tr_def.items {
|
||||||
Some(items) => {
|
Some(items) => {
|
||||||
let mut collector = AssocItemCollector::new(
|
let mut collector = AssocItemCollector::new(
|
||||||
|
@ -258,6 +266,7 @@ impl TraitData {
|
||||||
is_unsafe,
|
is_unsafe,
|
||||||
visibility,
|
visibility,
|
||||||
skip_array_during_method_dispatch,
|
skip_array_during_method_dispatch,
|
||||||
|
rustc_has_incoherent_inherent_impls,
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
|
||||||
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
|
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
|
||||||
FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
|
FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
|
||||||
};
|
};
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chalk_db,
|
chalk_db,
|
||||||
|
@ -92,10 +92,15 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
|
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
|
||||||
|
|
||||||
/// Collects all crates in the dependency graph that have impls for the
|
/// Collects all crates in the dependency graph that have impls for the
|
||||||
/// given fingerprint. This is only used for primitive types; for
|
/// given fingerprint. This is only used for primitive types and types
|
||||||
/// user-defined types we just look at the crate where the type is defined.
|
/// annotated with `rustc_has_incoherent_inherent_impls`; for other types
|
||||||
#[salsa::invoke(crate::method_resolution::inherent_impl_crates_query)]
|
/// we just look at the crate where the type is defined.
|
||||||
fn inherent_impl_crates(&self, krate: CrateId, fp: TyFingerprint) -> ArrayVec<CrateId, 2>;
|
#[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)]
|
||||||
|
fn incoherent_inherent_impl_crates(
|
||||||
|
&self,
|
||||||
|
krate: CrateId,
|
||||||
|
fp: TyFingerprint,
|
||||||
|
) -> SmallVec<[CrateId; 2]>;
|
||||||
|
|
||||||
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
||||||
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
//! For details about how this works in rustc, see the method lookup page in the
|
//! For details about how this works in rustc, see the method lookup page in the
|
||||||
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
|
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
|
||||||
//! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
|
//! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
|
||||||
use std::{iter, ops::ControlFlow, sync::Arc};
|
use std::{ops::ControlFlow, sync::Arc};
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
|
||||||
use base_db::{CrateId, Edition};
|
use base_db::{CrateId, Edition};
|
||||||
use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
|
use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
|
data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
|
||||||
FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId,
|
FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||||
TraitId,
|
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -336,21 +335,18 @@ impl InherentImpls {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn inherent_impl_crates_query(
|
pub(crate) fn incoherent_inherent_impl_crates(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
fp: TyFingerprint,
|
fp: TyFingerprint,
|
||||||
) -> ArrayVec<CrateId, 2> {
|
) -> SmallVec<[CrateId; 2]> {
|
||||||
let _p = profile::span("inherent_impl_crates_query");
|
let _p = profile::span("inherent_impl_crates_query");
|
||||||
let mut res = ArrayVec::new();
|
let mut res = SmallVec::new();
|
||||||
let crate_graph = db.crate_graph();
|
let crate_graph = db.crate_graph();
|
||||||
|
|
||||||
|
// should pass crate for finger print and do reverse deps
|
||||||
|
|
||||||
for krate in crate_graph.transitive_deps(krate) {
|
for krate in crate_graph.transitive_deps(krate) {
|
||||||
if res.is_full() {
|
|
||||||
// we don't currently look for or store more than two crates here,
|
|
||||||
// so don't needlessly look at more crates than necessary.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let impls = db.inherent_impls_in_crate(krate);
|
let impls = db.inherent_impls_in_crate(krate);
|
||||||
if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) {
|
if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) {
|
||||||
res.push(krate);
|
res.push(krate);
|
||||||
|
@ -392,19 +388,40 @@ pub fn def_crates(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
ty: &Ty,
|
ty: &Ty,
|
||||||
cur_crate: CrateId,
|
cur_crate: CrateId,
|
||||||
) -> Option<ArrayVec<CrateId, 2>> {
|
) -> Option<SmallVec<[CrateId; 2]>> {
|
||||||
let mod_to_crate_ids = |module: ModuleId| Some(iter::once(module.krate()).collect());
|
|
||||||
|
|
||||||
let fp = TyFingerprint::for_inherent_impl(ty);
|
|
||||||
|
|
||||||
match ty.kind(Interner) {
|
match ty.kind(Interner) {
|
||||||
TyKind::Adt(AdtId(def_id), _) => mod_to_crate_ids(def_id.module(db.upcast())),
|
&TyKind::Adt(AdtId(def_id), _) => {
|
||||||
TyKind::Foreign(id) => {
|
let rustc_has_incoherent_inherent_impls = match def_id {
|
||||||
mod_to_crate_ids(from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()))
|
hir_def::AdtId::StructId(id) => {
|
||||||
|
db.struct_data(id).rustc_has_incoherent_inherent_impls
|
||||||
|
}
|
||||||
|
hir_def::AdtId::UnionId(id) => {
|
||||||
|
db.union_data(id).rustc_has_incoherent_inherent_impls
|
||||||
|
}
|
||||||
|
hir_def::AdtId::EnumId(id) => db.enum_data(id).rustc_has_incoherent_inherent_impls,
|
||||||
|
};
|
||||||
|
Some(if rustc_has_incoherent_inherent_impls {
|
||||||
|
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Adt(def_id))
|
||||||
|
} else {
|
||||||
|
smallvec![def_id.module(db.upcast()).krate()]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
&TyKind::Foreign(id) => {
|
||||||
|
let alias = from_foreign_def_id(id);
|
||||||
|
Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls {
|
||||||
|
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id))
|
||||||
|
} else {
|
||||||
|
smallvec![alias.module(db.upcast()).krate()]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
TyKind::Dyn(_) => {
|
||||||
|
let trait_id = ty.dyn_trait()?;
|
||||||
|
Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls {
|
||||||
|
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
|
||||||
|
} else {
|
||||||
|
smallvec![trait_id.module(db.upcast()).krate()]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
TyKind::Dyn(_) => ty
|
|
||||||
.dyn_trait()
|
|
||||||
.and_then(|trait_| mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))),
|
|
||||||
// for primitives, there may be impls in various places (core and alloc
|
// for primitives, there may be impls in various places (core and alloc
|
||||||
// mostly). We just check the whole crate graph for crates with impls
|
// mostly). We just check the whole crate graph for crates with impls
|
||||||
// (cached behind a query).
|
// (cached behind a query).
|
||||||
|
@ -412,10 +429,11 @@ pub fn def_crates(
|
||||||
| TyKind::Str
|
| TyKind::Str
|
||||||
| TyKind::Slice(_)
|
| TyKind::Slice(_)
|
||||||
| TyKind::Array(..)
|
| TyKind::Array(..)
|
||||||
| TyKind::Raw(..) => {
|
| TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates(
|
||||||
Some(db.inherent_impl_crates(cur_crate, fp.expect("fingerprint for primitive")))
|
cur_crate,
|
||||||
}
|
TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"),
|
||||||
_ => return None,
|
)),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1867,3 +1867,32 @@ fn g<T: Trait>(a: T) {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incoherent_impls() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: error, send
|
||||||
|
pub struct Box<T>(T);
|
||||||
|
use core::error::Error;
|
||||||
|
|
||||||
|
#[rustc_allow_incoherent_impl]
|
||||||
|
impl dyn Error {
|
||||||
|
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rustc_allow_incoherent_impl]
|
||||||
|
impl dyn Error + Send {
|
||||||
|
/// Attempts to downcast the box to a concrete type.
|
||||||
|
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
|
||||||
|
let err: Box<dyn Error> = self;
|
||||||
|
// ^^^^ expected Box<dyn Error>, got Box<dyn Error + Send>
|
||||||
|
// FIXME, type mismatch should not occur
|
||||||
|
<dyn Error>::downcast(err).map_err(|_| loop {})
|
||||||
|
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error>) -> Result<Box<{unknown}>, Box<dyn Error>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
//! derive:
|
//! derive:
|
||||||
//! drop:
|
//! drop:
|
||||||
//! eq: sized
|
//! eq: sized
|
||||||
|
//! error: fmt
|
||||||
//! fmt: result
|
//! fmt: result
|
||||||
//! fn:
|
//! fn:
|
||||||
//! from: sized
|
//! from: sized
|
||||||
|
@ -34,8 +35,10 @@
|
||||||
//! pin:
|
//! pin:
|
||||||
//! range:
|
//! range:
|
||||||
//! result:
|
//! result:
|
||||||
|
//! send: sized
|
||||||
//! sized:
|
//! sized:
|
||||||
//! slice:
|
//! slice:
|
||||||
|
//! sync: sized
|
||||||
//! try:
|
//! try:
|
||||||
//! unsize: sized
|
//! unsize: sized
|
||||||
|
|
||||||
|
@ -47,6 +50,24 @@ pub mod marker {
|
||||||
pub trait Sized {}
|
pub trait Sized {}
|
||||||
// endregion:sized
|
// endregion:sized
|
||||||
|
|
||||||
|
// region:send
|
||||||
|
pub unsafe auto trait Send {}
|
||||||
|
|
||||||
|
impl<T: ?Sized> !Send for *const T {}
|
||||||
|
impl<T: ?Sized> !Send for *mut T {}
|
||||||
|
// region:sync
|
||||||
|
unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||||
|
unsafe impl<T: Send + ?Sized> Send for &mut T {}
|
||||||
|
// endregion:sync
|
||||||
|
// endregion:send
|
||||||
|
|
||||||
|
// region:sync
|
||||||
|
pub unsafe auto trait Sync {}
|
||||||
|
|
||||||
|
impl<T: ?Sized> !Sync for *const T {}
|
||||||
|
impl<T: ?Sized> !Sync for *mut T {}
|
||||||
|
// endregion:sync
|
||||||
|
|
||||||
// region:unsize
|
// region:unsize
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
pub trait Unsize<T: ?Sized> {}
|
pub trait Unsize<T: ?Sized> {}
|
||||||
|
@ -438,6 +459,9 @@ pub mod fmt {
|
||||||
pub trait Debug {
|
pub trait Debug {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
}
|
}
|
||||||
|
pub trait Display {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// endregion:fmt
|
// endregion:fmt
|
||||||
|
|
||||||
|
@ -693,6 +717,17 @@ impl bool {
|
||||||
}
|
}
|
||||||
// endregion:bool_impl
|
// endregion:bool_impl
|
||||||
|
|
||||||
|
// region:error
|
||||||
|
pub mod error {
|
||||||
|
#[rustc_has_incoherent_inherent_impls]
|
||||||
|
pub trait Error: crate::fmt::Debug + crate::fmt::Display {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion:error
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub mod v1 {
|
pub mod v1 {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -705,7 +740,9 @@ pub mod prelude {
|
||||||
iter::{IntoIterator, Iterator}, // :iterator
|
iter::{IntoIterator, Iterator}, // :iterator
|
||||||
macros::builtin::derive, // :derive
|
macros::builtin::derive, // :derive
|
||||||
marker::Copy, // :copy
|
marker::Copy, // :copy
|
||||||
|
marker::Send, // :send
|
||||||
marker::Sized, // :sized
|
marker::Sized, // :sized
|
||||||
|
marker::Sync, // :sync
|
||||||
mem::drop, // :drop
|
mem::drop, // :drop
|
||||||
ops::Drop, // :drop
|
ops::Drop, // :drop
|
||||||
ops::{Fn, FnMut, FnOnce}, // :fn
|
ops::{Fn, FnMut, FnOnce}, // :fn
|
||||||
|
|
Loading…
Reference in a new issue