Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Diagnose some orphan trait impl cases #15891

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false };
if let DefWithBodyId::FunctionId(it) = owner {
p.buf.push('(');
body.params.iter().zip(&db.function_data(it).params).for_each(|(&param, ty)| {
body.params.iter().zip(db.function_data(it).params.iter()).for_each(|(&param, ty)| {
p.print_pat(param);
p.buf.push(':');
p.print_type_ref(ty);
Expand Down
6 changes: 3 additions & 3 deletions crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::{
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionData {
pub name: Name,
pub params: Vec<Interned<TypeRef>>,
pub params: Box<[Interned<TypeRef>]>,
pub ret_type: Interned<TypeRef>,
pub attrs: Attrs,
pub visibility: RawVisibility,
Expand Down Expand Up @@ -177,7 +177,7 @@ pub struct TypeAliasData {
pub rustc_has_incoherent_inherent_impls: bool,
pub rustc_allow_incoherent_impl: bool,
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
pub bounds: Vec<Interned<TypeBound>>,
pub bounds: Box<[Interned<TypeBound>]>,
}

impl TypeAliasData {
Expand Down Expand Up @@ -210,7 +210,7 @@ impl TypeAliasData {
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
rustc_has_incoherent_inherent_impls,
rustc_allow_incoherent_impl,
bounds: typ.bounds.to_vec(),
bounds: typ.bounds.clone(),
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ impl GenericParams {
let mut expander = Lazy::new(|| {
(module.def_map(db), Expander::new(db, loc.source(db).file_id, module))
});
for param in &func_data.params {
for param in func_data.params.iter() {
generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
}

Expand Down
13 changes: 3 additions & 10 deletions crates/hir-def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,7 @@ impl<'a> Ctx<'a> {
let bounds = self.lower_type_bounds(type_alias);
let generic_params = self.lower_generic_params(HasImplicitSelf::No, type_alias);
let ast_id = self.source_ast_id_map.ast_id(type_alias);
let res = TypeAlias {
name,
visibility,
bounds: bounds.into_boxed_slice(),
generic_params,
type_ref,
ast_id,
};
let res = TypeAlias { name, visibility, bounds, generic_params, type_ref, ast_id };
Some(id(self.data().type_aliases.alloc(res)))
}

Expand Down Expand Up @@ -637,13 +630,13 @@ impl<'a> Ctx<'a> {
Interned::new(generics)
}

fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Vec<Interned<TypeBound>> {
fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned<TypeBound>]> {
match node.type_bound_list() {
Some(bound_list) => bound_list
.bounds()
.map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it)))
.collect(),
None => Vec::new(),
None => Box::default(),
}
}

Expand Down
26 changes: 11 additions & 15 deletions crates/hir-ty/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use crate::{
method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
mir::{BorrowckResult, MirBody, MirLowerError},
Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, InferenceResult,
Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, Substitution, TraitRef, Ty,
TyDefId, ValueTyDefId,
Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, Substitution,
TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId,
};
use hir_expand::name::Name;

Expand All @@ -47,15 +47,15 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
&self,
def: DefWithBodyId,
subst: Substitution,
env: Arc<crate::TraitEnvironment>,
env: Arc<TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError>;

#[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)]
fn monomorphized_mir_body_for_closure(
&self,
def: ClosureId,
subst: Substitution,
env: Arc<crate::TraitEnvironment>,
env: Arc<TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError>;

#[salsa::invoke(crate::mir::borrowck_query)]
Expand All @@ -81,7 +81,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
&self,
def: GeneralConstId,
subst: Substitution,
trait_env: Option<Arc<crate::TraitEnvironment>>,
trait_env: Option<Arc<TraitEnvironment>>,
) -> Result<Const, ConstEvalError>;

#[salsa::invoke(crate::consteval::const_eval_static_query)]
Expand All @@ -104,24 +104,20 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
&self,
def: AdtId,
subst: Substitution,
env: Arc<crate::TraitEnvironment>,
env: Arc<TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError>;

#[salsa::invoke(crate::layout::layout_of_ty_query)]
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
fn layout_of_ty(
&self,
ty: Ty,
env: Arc<crate::TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError>;
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;

#[salsa::invoke(crate::layout::target_data_layout_query)]
fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;

#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
fn lookup_impl_method(
&self,
env: Arc<crate::TraitEnvironment>,
env: Arc<TraitEnvironment>,
func: FunctionId,
fn_subst: Substitution,
) -> (FunctionId, Substitution);
Expand Down Expand Up @@ -149,10 +145,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {

#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
#[salsa::transparent]
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<crate::TraitEnvironment>;
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>;

#[salsa::invoke(crate::lower::trait_environment_query)]
fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>;
fn trait_environment(&self, def: GenericDefId) -> Arc<TraitEnvironment>;

#[salsa::invoke(crate::lower::generic_defaults_query)]
#[salsa::cycle(crate::lower::generic_defaults_recover)]
Expand Down Expand Up @@ -249,7 +245,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
fn normalize_projection(
&self,
projection: crate::ProjectionTy,
env: Arc<crate::TraitEnvironment>,
env: Arc<TraitEnvironment>,
) -> Ty;

#[salsa::invoke(trait_solve_wait)]
Expand Down
6 changes: 0 additions & 6 deletions crates/hir-ty/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,3 @@ pub use crate::diagnostics::{
},
unsafe_check::{missing_unsafe, unsafe_expressions, UnsafeExpr},
};

#[derive(Debug, PartialEq, Eq)]
pub struct IncoherentImpl {
pub file_id: hir_expand::HirFileId,
pub impl_: syntax::AstPtr<syntax::ast::Impl>,
}
57 changes: 37 additions & 20 deletions crates/hir-ty/src/layout.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Compute the binary representation of a type

use std::fmt;

use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
use hir_def::{
layout::{
Expand All @@ -26,12 +28,6 @@ pub use self::{
target::target_data_layout_query,
};

macro_rules! user_error {
($it: expr) => {
return Err(LayoutError::UserError(format!($it).into()))
};
}

mod adt;
mod target;

Expand Down Expand Up @@ -73,13 +69,38 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LayoutError {
UserError(Box<str>),
SizeOverflow,
TargetLayoutNotAvailable,
HasPlaceholder,
HasErrorConst,
HasErrorType,
HasPlaceholder,
InvalidSimdType,
NotImplemented,
RecursiveTypeWithoutIndirection,
SizeOverflow,
TargetLayoutNotAvailable,
Unknown,
UserReprTooSmall,
}

impl std::error::Error for LayoutError {}
impl fmt::Display for LayoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"),
LayoutError::HasErrorType => write!(f, "type contains an error"),
LayoutError::HasPlaceholder => write!(f, "type contains placeholders"),
LayoutError::InvalidSimdType => write!(f, "invalid simd type definition"),
LayoutError::NotImplemented => write!(f, "not implemented"),
LayoutError::RecursiveTypeWithoutIndirection => {
write!(f, "recursive type without indirection")
}
LayoutError::SizeOverflow => write!(f, "size overflow"),
LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"),
LayoutError::Unknown => write!(f, "unknown"),
LayoutError::UserReprTooSmall => {
write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum")
}
}
}
}

struct LayoutCx<'a> {
Expand Down Expand Up @@ -118,9 +139,7 @@ fn layout_of_simd_ty(

let f0_ty = match fields.iter().next() {
Some(it) => it.1.clone().substitute(Interner, subst),
None => {
user_error!("simd type with zero fields");
}
None => return Err(LayoutError::InvalidSimdType),
};

// The element type and number of elements of the SIMD vector
Expand All @@ -134,7 +153,7 @@ fn layout_of_simd_ty(
// Extract the number of elements from the layout of the array field:
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
else {
user_error!("Array with non array layout");
return Err(LayoutError::Unknown);
};

(e_ty.clone(), count, true)
Expand All @@ -146,7 +165,7 @@ fn layout_of_simd_ty(
// Compute the ABI of the element type:
let e_ly = db.layout_of_ty(e_ty, env.clone())?;
let Abi::Scalar(e_abi) = e_ly.abi else {
user_error!("simd type with inner non scalar type");
return Err(LayoutError::Unknown);
};

// Compute the size and alignment of the vector:
Expand Down Expand Up @@ -259,9 +278,7 @@ pub fn layout_of_ty_query(
cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)?
}
TyKind::Array(element, count) => {
let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(Box::from(
"unevaluated or mistyped const generic parameter",
)))? as u64;
let count = try_const_usize(db, &count).ok_or(LayoutError::HasErrorConst)? as u64;
let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;

Expand Down Expand Up @@ -352,7 +369,7 @@ pub fn layout_of_ty_query(
let mut unit = layout_of_unit(&cx, dl)?;
match unit.abi {
Abi::Aggregate { ref mut sized } => *sized = false,
_ => user_error!("bug"),
_ => return Err(LayoutError::Unknown),
}
unit
}
Expand Down Expand Up @@ -418,7 +435,7 @@ pub fn layout_of_ty_recover(
_: &Ty,
_: &Arc<TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError> {
user_error!("infinite sized recursive type");
Err(LayoutError::RecursiveTypeWithoutIndirection)
}

fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> {
Expand Down
8 changes: 2 additions & 6 deletions crates/hir-ty/src/layout/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub fn layout_of_adt_recover(
_: &Substitution,
_: &Arc<TraitEnvironment>,
) -> Result<Arc<Layout>, LayoutError> {
user_error!("infinite sized recursive type");
Err(LayoutError::RecursiveTypeWithoutIndirection)
}

/// Finds the appropriate Integer type and signedness for the given
Expand All @@ -169,11 +169,7 @@ fn repr_discr(
let discr = Integer::from_attr(dl, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
if discr < fit {
return Err(LayoutError::UserError(
"Integer::repr_discr: `#[repr]` hint too small for \
discriminant range of enum "
.into(),
));
return Err(LayoutError::UserReprTooSmall);
}
return Ok((discr, ity.is_signed()));
}
Expand Down
7 changes: 2 additions & 5 deletions crates/hir-ty/src/layout/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,13 @@ fn recursive() {
struct BoxLike<T: ?Sized>(*mut T);
struct Goal(BoxLike<Goal>);
}
check_fail(
r#"struct Goal(Goal);"#,
LayoutError::UserError("infinite sized recursive type".into()),
);
check_fail(r#"struct Goal(Goal);"#, LayoutError::RecursiveTypeWithoutIndirection);
check_fail(
r#"
struct Foo<T>(Foo<T>);
struct Goal(Foo<i32>);
"#,
LayoutError::UserError("infinite sized recursive type".into()),
LayoutError::RecursiveTypeWithoutIndirection,
);
}

Expand Down
1 change: 1 addition & 0 deletions crates/hir-ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pub use mapping::{
lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
to_placeholder_idx,
};
pub use method_resolution::check_orphan_rules;
pub use traits::TraitEnvironment;
pub use utils::{all_super_traits, is_fn_unsafe_to_call};

Expand Down