mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-04 01:08:47 +00:00
Introduce StructFlags
This commit is contained in:
parent
251b3a47af
commit
33b6012827
8 changed files with 93 additions and 58 deletions
|
@ -3,6 +3,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
use bitflags::bitflags;
|
||||||
use cfg::CfgOptions;
|
use cfg::CfgOptions;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ use crate::{
|
||||||
builtin_type::{BuiltinInt, BuiltinUint},
|
builtin_type::{BuiltinInt, BuiltinUint},
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
|
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||||
|
lang_item::LangItem,
|
||||||
layout::{Align, ReprFlags, ReprOptions},
|
layout::{Align, ReprFlags, ReprOptions},
|
||||||
nameres::diagnostics::DefDiagnostic,
|
nameres::diagnostics::DefDiagnostic,
|
||||||
src::HasChildSource,
|
src::HasChildSource,
|
||||||
|
@ -39,8 +41,26 @@ pub struct StructData {
|
||||||
pub variant_data: Arc<VariantData>,
|
pub variant_data: Arc<VariantData>,
|
||||||
pub repr: Option<ReprOptions>,
|
pub repr: Option<ReprOptions>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub rustc_has_incoherent_inherent_impls: bool,
|
pub flags: StructFlags,
|
||||||
pub fundamental: bool,
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct StructFlags: u8 {
|
||||||
|
const NO_FLAGS = 0;
|
||||||
|
/// Indicates whether the struct is `PhantomData`.
|
||||||
|
const IS_PHANTOM_DATA = 1 << 2;
|
||||||
|
/// Indicates whether the struct has a `#[fundamental]` attribute.
|
||||||
|
const IS_FUNDAMENTAL = 1 << 3;
|
||||||
|
// FIXME: should this be a flag?
|
||||||
|
/// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute.
|
||||||
|
const IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL = 1 << 4;
|
||||||
|
/// Indicates whether this struct is `Box`.
|
||||||
|
const IS_BOX = 1 << 5;
|
||||||
|
/// Indicates whether this struct is `ManuallyDrop`.
|
||||||
|
const IS_MANUALLY_DROP = 1 << 6;
|
||||||
|
/// Indicates whether this struct is `UnsafeCell`.
|
||||||
|
const IS_UNSAFE_CELL = 1 << 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -174,10 +194,25 @@ 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 attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
||||||
let rustc_has_incoherent_inherent_impls =
|
|
||||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
let mut flags = StructFlags::NO_FLAGS;
|
||||||
let fundamental = attrs.by_key("fundamental").exists();
|
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
|
||||||
|
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
|
||||||
|
}
|
||||||
|
if attrs.by_key("fundamental").exists() {
|
||||||
|
flags |= StructFlags::IS_FUNDAMENTAL;
|
||||||
|
}
|
||||||
|
if let Some(lang) = attrs.lang_item() {
|
||||||
|
match lang {
|
||||||
|
LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA,
|
||||||
|
LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
|
||||||
|
LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
|
||||||
|
LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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(
|
||||||
|
@ -196,8 +231,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,
|
flags,
|
||||||
fundamental,
|
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
@ -218,9 +252,13 @@ impl StructData {
|
||||||
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 attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
||||||
let rustc_has_incoherent_inherent_impls =
|
let mut flags = StructFlags::NO_FLAGS;
|
||||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
|
||||||
let fundamental = attrs.by_key("fundamental").exists();
|
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
|
||||||
|
}
|
||||||
|
if attrs.by_key("fundamental").exists() {
|
||||||
|
flags |= StructFlags::IS_FUNDAMENTAL;
|
||||||
|
}
|
||||||
|
|
||||||
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(
|
||||||
|
@ -239,8 +277,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,
|
flags,
|
||||||
fundamental,
|
|
||||||
}),
|
}),
|
||||||
diagnostics.into(),
|
diagnostics.into(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,6 +20,7 @@ use syntax::{
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
|
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
|
||||||
|
lang_item::LangItem,
|
||||||
nameres::{ModuleOrigin, ModuleSource},
|
nameres::{ModuleOrigin, ModuleSource},
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
|
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
|
||||||
|
@ -175,13 +176,13 @@ impl Attrs {
|
||||||
|
|
||||||
Arc::new(res)
|
Arc::new(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
|
|
||||||
AttrQuery { attrs: self, key }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attrs {
|
impl Attrs {
|
||||||
|
pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
|
||||||
|
AttrQuery { attrs: self, key }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cfg(&self) -> Option<CfgExpr> {
|
pub fn cfg(&self) -> Option<CfgExpr> {
|
||||||
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
|
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
|
||||||
let first = cfgs.next()?;
|
let first = cfgs.next()?;
|
||||||
|
@ -204,6 +205,10 @@ impl Attrs {
|
||||||
self.by_key("lang").string_value()
|
self.by_key("lang").string_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lang_item(&self) -> Option<LangItem> {
|
||||||
|
self.by_key("lang").string_value().and_then(|it| LangItem::from_str(it))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn docs(&self) -> Option<Documentation> {
|
pub fn docs(&self) -> Option<Documentation> {
|
||||||
let docs = self.by_key("doc").attrs().filter_map(|attr| attr.string_value());
|
let docs = self.by_key("doc").attrs().filter_map(|attr| attr.string_value());
|
||||||
let indent = doc_indent(self);
|
let indent = doc_indent(self);
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
|
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
|
||||||
|
|
||||||
use chalk_ir::cast::Cast;
|
use chalk_ir::cast::Cast;
|
||||||
use hir_def::{
|
use hir_def::lang_item::LangItem;
|
||||||
lang_item::{LangItem, LangItemTarget},
|
|
||||||
AdtId,
|
|
||||||
};
|
|
||||||
use hir_expand::name::name;
|
use hir_expand::name::name;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
|
|
||||||
|
@ -90,13 +87,8 @@ pub(crate) fn builtin_deref<'ty>(
|
||||||
TyKind::Ref(.., ty) => Some(ty),
|
TyKind::Ref(.., ty) => Some(ty),
|
||||||
// FIXME: Maybe accept this but diagnose if its not explicit?
|
// FIXME: Maybe accept this but diagnose if its not explicit?
|
||||||
TyKind::Raw(.., ty) if explicit => Some(ty),
|
TyKind::Raw(.., ty) if explicit => Some(ty),
|
||||||
&TyKind::Adt(chalk_ir::AdtId(AdtId::StructId(strukt)), ref substs) => {
|
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
|
||||||
if Some(strukt)
|
if crate::lang_items::is_box(table.db, adt) {
|
||||||
== table
|
|
||||||
.db
|
|
||||||
.lang_item(table.trait_env.krate, LangItem::OwnedBox)
|
|
||||||
.and_then(LangItemTarget::as_struct)
|
|
||||||
{
|
|
||||||
substs.at(Interner, 0).ty(Interner)
|
substs.at(Interner, 0).ty(Interner)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -379,7 +379,7 @@ impl HirDisplay for Pat {
|
||||||
}
|
}
|
||||||
PatKind::Deref { subpattern } => {
|
PatKind::Deref { subpattern } => {
|
||||||
match self.ty.kind(Interner) {
|
match self.ty.kind(Interner) {
|
||||||
TyKind::Adt(adt, _) if is_box(adt.0, f.db) => write!(f, "box ")?,
|
TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?,
|
||||||
&TyKind::Ref(mutbl, ..) => {
|
&TyKind::Ref(mutbl, ..) => {
|
||||||
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
|
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,7 +384,7 @@ impl Constructor {
|
||||||
TyKind::Tuple(arity, ..) => arity,
|
TyKind::Tuple(arity, ..) => arity,
|
||||||
TyKind::Ref(..) => 1,
|
TyKind::Ref(..) => 1,
|
||||||
TyKind::Adt(adt, ..) => {
|
TyKind::Adt(adt, ..) => {
|
||||||
if is_box(adt.0, pcx.cx.db) {
|
if is_box(pcx.cx.db, adt.0) {
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
1
|
1
|
||||||
|
@ -800,7 +800,7 @@ impl<'p> Fields<'p> {
|
||||||
}
|
}
|
||||||
TyKind::Ref(.., rty) => Fields::wildcards_from_tys(cx, once(rty.clone())),
|
TyKind::Ref(.., rty) => Fields::wildcards_from_tys(cx, once(rty.clone())),
|
||||||
&TyKind::Adt(AdtId(adt), ref substs) => {
|
&TyKind::Adt(AdtId(adt), ref substs) => {
|
||||||
if is_box(adt, cx.db) {
|
if is_box(cx.db, adt) {
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
|
let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
|
||||||
|
@ -905,7 +905,7 @@ impl<'p> DeconstructedPat<'p> {
|
||||||
}
|
}
|
||||||
fields = Fields::from_iter(cx, wilds)
|
fields = Fields::from_iter(cx, wilds)
|
||||||
}
|
}
|
||||||
TyKind::Adt(adt, substs) if is_box(adt.0, cx.db) => {
|
TyKind::Adt(adt, substs) if is_box(cx.db, adt.0) => {
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
|
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
|
||||||
|
@ -992,7 +992,7 @@ impl<'p> DeconstructedPat<'p> {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
TyKind::Adt(adt, _) if is_box(adt.0, cx.db) => {
|
TyKind::Adt(adt, _) if is_box(cx.db, adt.0) => {
|
||||||
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
|
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
|
||||||
// of `std`). So this branch is only reachable when the feature is enabled and
|
// of `std`). So this branch is only reachable when the feature is enabled and
|
||||||
// the pattern is a box pattern.
|
// the pattern is a box pattern.
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
//! Functions to detect special lang items
|
//! Functions to detect special lang items
|
||||||
|
|
||||||
use hir_def::{lang_item::LangItem, AdtId, HasModule};
|
use hir_def::{adt::StructFlags, lang_item::LangItem, AdtId};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
|
|
||||||
use crate::db::HirDatabase;
|
use crate::db::HirDatabase;
|
||||||
|
|
||||||
pub fn is_box(adt: AdtId, db: &dyn HirDatabase) -> bool {
|
pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
|
||||||
let krate = adt.module(db.upcast()).krate();
|
let AdtId::StructId(id) = adt else { return false };
|
||||||
let box_adt =
|
db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
|
||||||
db.lang_item(krate, LangItem::OwnedBox).and_then(|it| it.as_struct()).map(AdtId::from);
|
|
||||||
Some(adt) == box_adt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unsafe_cell(adt: AdtId, db: &dyn HirDatabase) -> bool {
|
pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool {
|
||||||
let krate = adt.module(db.upcast()).krate();
|
let AdtId::StructId(id) = adt else { return false };
|
||||||
let box_adt =
|
db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
|
||||||
db.lang_item(krate, LangItem::UnsafeCell).and_then(|it| it.as_struct()).map(AdtId::from);
|
|
||||||
Some(adt) == box_adt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {
|
pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub fn layout_of_adt_query(
|
||||||
&repr,
|
&repr,
|
||||||
&variants,
|
&variants,
|
||||||
is_enum,
|
is_enum,
|
||||||
is_unsafe_cell(def, db),
|
is_unsafe_cell(db, def),
|
||||||
layout_scalar_valid_range(db, def),
|
layout_scalar_valid_range(db, def),
|
||||||
|min, max| Integer::repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
|
|min, max| Integer::repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
|
||||||
variants.iter_enumerated().filter_map(|(id, _)| {
|
variants.iter_enumerated().filter_map(|(id, _)| {
|
||||||
|
|
|
@ -7,8 +7,9 @@ use std::{ops::ControlFlow, sync::Arc};
|
||||||
use base_db::{CrateId, Edition};
|
use base_db::{CrateId, Edition};
|
||||||
use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
|
use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
|
adt::StructFlags, data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId,
|
||||||
FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
|
ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId,
|
||||||
|
TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
@ -405,12 +406,14 @@ pub fn def_crates(
|
||||||
match ty.kind(Interner) {
|
match ty.kind(Interner) {
|
||||||
&TyKind::Adt(AdtId(def_id), _) => {
|
&TyKind::Adt(AdtId(def_id), _) => {
|
||||||
let rustc_has_incoherent_inherent_impls = match def_id {
|
let rustc_has_incoherent_inherent_impls = match def_id {
|
||||||
hir_def::AdtId::StructId(id) => {
|
hir_def::AdtId::StructId(id) => db
|
||||||
db.struct_data(id).rustc_has_incoherent_inherent_impls
|
.struct_data(id)
|
||||||
}
|
.flags
|
||||||
hir_def::AdtId::UnionId(id) => {
|
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
|
||||||
db.union_data(id).rustc_has_incoherent_inherent_impls
|
hir_def::AdtId::UnionId(id) => db
|
||||||
}
|
.union_data(id)
|
||||||
|
.flags
|
||||||
|
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
|
||||||
hir_def::AdtId::EnumId(id) => db.enum_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 {
|
Some(if rustc_has_incoherent_inherent_impls {
|
||||||
|
@ -808,12 +811,14 @@ fn is_inherent_impl_coherent(
|
||||||
| TyKind::Scalar(_) => true,
|
| TyKind::Scalar(_) => true,
|
||||||
|
|
||||||
&TyKind::Adt(AdtId(adt), _) => match adt {
|
&TyKind::Adt(AdtId(adt), _) => match adt {
|
||||||
hir_def::AdtId::StructId(it) => {
|
hir_def::AdtId::StructId(id) => db
|
||||||
db.struct_data(it).rustc_has_incoherent_inherent_impls
|
.struct_data(id)
|
||||||
}
|
.flags
|
||||||
hir_def::AdtId::UnionId(it) => {
|
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
|
||||||
db.union_data(it).rustc_has_incoherent_inherent_impls
|
hir_def::AdtId::UnionId(id) => db
|
||||||
}
|
.union_data(id)
|
||||||
|
.flags
|
||||||
|
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
|
||||||
hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
|
hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
|
||||||
},
|
},
|
||||||
TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
|
TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
|
||||||
|
|
Loading…
Reference in a new issue