Skip to content

Commit

Permalink
Auto merge of #17984 - ShoyuVanilla:cast, r=Veykril
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Sep 3, 2024
2 parents 1fddb11 + d186bdc commit 6e84451
Show file tree
Hide file tree
Showing 25 changed files with 1,614 additions and 93 deletions.
22 changes: 22 additions & 0 deletions crates/hir-def/src/data/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use triomphe::Arc;
use crate::{
builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
hir::Expr,
item_tree::{
AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
},
Expand Down Expand Up @@ -317,6 +318,27 @@ impl EnumData {
_ => IntegerType::Pointer(true),
}
}

// [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448)
pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool {
self.variants.iter().all(|(v, _)| {
// The condition check order is slightly modified from rustc
// to improve performance by early returning with relatively fast checks
let variant = &db.enum_variant_data(*v).variant_data;
if !variant.fields().is_empty() {
return false;
}
// The outer if condition is whether this variant has const ctor or not
if !matches!(variant.kind(), StructKind::Unit) {
let body = db.body((*v).into());
// A variant with explicit discriminant
if body.exprs[body.body_expr] != Expr::Missing {
return false;
}
}
true
})
}
}

impl EnumVariantData {
Expand Down
21 changes: 18 additions & 3 deletions crates/hir-ty/src/consteval/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,13 @@ fn floating_point() {

#[test]
fn casts() {
check_number(r#"const GOAL: usize = 12 as *const i32 as usize"#, 12);
check_number(
r#"
//- minicore: sized
const GOAL: usize = 12 as *const i32 as usize
"#,
12,
);
check_number(
r#"
//- minicore: coerce_unsized, index, slice
Expand All @@ -204,7 +210,7 @@ fn casts() {
r#"
//- minicore: coerce_unsized, index, slice
const GOAL: i16 = {
let a = &mut 5;
let a = &mut 5_i16;
let z = a as *mut _;
unsafe { *z }
};
Expand Down Expand Up @@ -244,7 +250,13 @@ fn casts() {
"#,
4,
);
check_number(r#"const GOAL: i32 = -12i8 as i32"#, -12);
check_number(
r#"
//- minicore: sized
const GOAL: i32 = -12i8 as i32
"#,
-12,
);
}

#[test]
Expand Down Expand Up @@ -1911,6 +1923,7 @@ fn function_pointer() {
);
check_number(
r#"
//- minicore: sized
fn add2(x: u8) -> u8 {
x + 2
}
Expand Down Expand Up @@ -2422,6 +2435,7 @@ fn statics() {
fn extern_weak_statics() {
check_number(
r#"
//- minicore: sized
extern "C" {
#[linkage = "extern_weak"]
static __dso_handle: *mut u8;
Expand Down Expand Up @@ -2716,6 +2730,7 @@ fn const_trait_assoc() {
);
check_number(
r#"
//- minicore: sized
struct S<T>(*mut T);
trait MySized: Sized {
Expand Down
1 change: 1 addition & 0 deletions crates/hir-ty/src/consteval/tests/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ fn saturating() {
fn allocator() {
check_number(
r#"
//- minicore: sized
extern "Rust" {
#[rustc_allocator]
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
Expand Down
32 changes: 27 additions & 5 deletions crates/hir-ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//! to certain types. To record this, we use the union-find implementation from
//! the `ena` crate, which is extracted from rustc.

mod cast;
pub(crate) mod cast;
pub(crate) mod closure;
mod coerce;
mod expr;
Expand Down Expand Up @@ -76,7 +76,7 @@ pub use coerce::could_coerce;
#[allow(unreachable_pub)]
pub use unify::{could_unify, could_unify_deeply};

use cast::CastCheck;
use cast::{CastCheck, CastError};
pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy};

/// The entry point of type inference.
Expand Down Expand Up @@ -254,6 +254,16 @@ pub enum InferenceDiagnostic {
expr: ExprId,
expected: Ty,
},
CastToUnsized {
expr: ExprId,
cast_ty: Ty,
},
InvalidCast {
expr: ExprId,
error: CastError,
expr_ty: Ty,
cast_ty: Ty,
},
}

/// A mismatch between an expected and an inferred type.
Expand Down Expand Up @@ -456,6 +466,7 @@ pub struct InferenceResult {
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
// FIXME: remove this field
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
pub coercion_casts: FxHashSet<ExprId>,
}

impl InferenceResult {
Expand Down Expand Up @@ -666,7 +677,7 @@ impl<'a> InferenceContext<'a> {
let InferenceContext {
mut table,
mut result,
deferred_cast_checks,
mut deferred_cast_checks,
tuple_field_accesses_rev,
..
} = self;
Expand Down Expand Up @@ -695,15 +706,26 @@ impl<'a> InferenceContext<'a> {
closure_info: _,
mutated_bindings_in_closure: _,
tuple_field_access_types: _,
coercion_casts,
} = &mut result;

table.fallback_if_possible();

// Comment from rustc:
// Even though coercion casts provide type hints, we check casts after fallback for
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
for cast in deferred_cast_checks {
cast.check(&mut table);
let mut apply_adjustments = |expr, adj| {
expr_adjustments.insert(expr, adj);
};
let mut set_coercion_cast = |expr| {
coercion_casts.insert(expr);
};
for cast in deferred_cast_checks.iter_mut() {
if let Err(diag) =
cast.check(&mut table, &mut apply_adjustments, &mut set_coercion_cast)
{
diagnostics.push(diag);
}
}

// FIXME resolve obligations as well (use Guidance if necessary)
Expand Down
Loading

0 comments on commit 6e84451

Please sign in to comment.