diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index fff62b11c647..750308026eec 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -308,6 +308,8 @@ impl LangItem { language_item_table! { // Variant name, Name, Getter method name, Target Generic requirements; Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); + MetaSized, sym::meta_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); + PointeeSized, sym::pointee_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 04a4635da412..7d49c26e8d6b 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -688,6 +688,7 @@ pub(crate) fn associated_ty_data_query( Arc::new(datum) } +// FIXME(sized-hierarchy) pub(crate) fn trait_datum_query( db: &dyn HirDatabase, krate: Crate, diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index ce53198e966f..7d80774d8712 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -86,6 +86,12 @@ pub use unify::{could_unify, could_unify_deeply}; use cast::{CastCheck, CastError}; pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub(crate) enum SizedTraitKind { + Sized, + MetaSized, +} + /// The entry point of type inference. pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { let _p = tracing::info_span!("infer_query").entered(); diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index 8d345defdc10..75dd76fadc8e 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -109,7 +109,7 @@ impl CastCheck { } if !self.cast_ty.data(Interner).flags.contains(TypeFlags::HAS_TY_INFER) - && !table.is_sized(&self.cast_ty) + && !table.has_trivial_sizedness(&self.cast_ty, super::SizedTraitKind::Sized) { return Err(InferenceDiagnostic::CastToUnsized { expr: self.expr, @@ -175,7 +175,7 @@ impl CastCheck { // array-ptr-cast CastTy::Ptr(t, m) => { let t = table.eagerly_normalize_and_resolve_shallow_in(t); - if !table.is_sized(&t) { + if !table.has_trivial_sizedness(&t, super::SizedTraitKind::Sized) { return Err(CastError::IllegalCast); } self.check_ref_cast( @@ -369,7 +369,7 @@ enum PointerKind { fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result, ()> { let ty = table.eagerly_normalize_and_resolve_shallow_in(ty.clone()); - if table.is_sized(&ty) { + if table.has_trivial_sizedness(&ty, super::SizedTraitKind::Sized) { return Ok(Some(PointerKind::Thin)); } diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index ce8a790ef642..ce993263697b 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -23,7 +23,7 @@ use crate::{ Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause, consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, - to_chalk_trait_id, traits::FnTrait, + infer::SizedTraitKind, to_chalk_trait_id, traits::FnTrait, }; impl InferenceContext<'_> { @@ -975,8 +975,8 @@ impl<'a> InferenceTable<'a> { } /// Check if given type is `Sized` or not - pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { - fn short_circuit_trivial_tys(ty: &Ty) -> Option { + pub(crate) fn has_trivial_sizedness(&mut self, ty: &Ty, sizedness: SizedTraitKind) -> bool { + fn short_circuit_trivial_tys(ty: &Ty, sizedness: SizedTraitKind) -> Option { match ty.kind(Interner) { TyKind::Scalar(..) | TyKind::Ref(..) @@ -985,14 +985,20 @@ impl<'a> InferenceTable<'a> { | TyKind::FnDef(..) | TyKind::Array(..) | TyKind::Function(..) => Some(true), - TyKind::Slice(..) | TyKind::Str | TyKind::Dyn(..) => Some(false), + TyKind::Slice(..) | TyKind::Str | TyKind::Dyn(..) => Some(match sizedness { + SizedTraitKind::Sized => false, + SizedTraitKind::MetaSized => true, + }), + TyKind::Foreign(_) => Some(match sizedness { + SizedTraitKind::Sized | SizedTraitKind::MetaSized => false, + }), _ => None, } } let mut ty = ty.clone(); ty = self.eagerly_normalize_and_resolve_shallow_in(ty); - if let Some(sized) = short_circuit_trivial_tys(&ty) { + if let Some(sized) = short_circuit_trivial_tys(&ty, sizedness) { return sized; } @@ -1015,7 +1021,7 @@ impl<'a> InferenceTable<'a> { // as unsized by the chalk, so we do this manually. ty = last_field_ty; ty = self.eagerly_normalize_and_resolve_shallow_in(ty); - if let Some(sized) = short_circuit_trivial_tys(&ty) { + if let Some(sized) = short_circuit_trivial_tys(&ty, sizedness) { return sized; } } else { @@ -1024,6 +1030,7 @@ impl<'a> InferenceTable<'a> { } } + // FIXME(sized-hierarchy): let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else { return false; }; diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 3c7333022402..b4f82b2ed9e4 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -42,7 +42,7 @@ use hir_def::{ use hir_expand::name::Name; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashSet; -use stdx::{impl_from, never}; +use stdx::{TupleExt, impl_from, never}; use triomphe::{Arc, ThinArc}; use crate::{ @@ -588,16 +588,28 @@ impl<'a> TyLoweringContext<'a> { clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref))); } } + // FIXME(sized-hierarchy) &TypeBound::Path(path, TraitBoundModifier::Maybe) => { let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate()); // Don't lower associated type bindings as the only possible relaxed trait bound // `?Sized` has no of them. // If we got another trait here ignore the bound completely. - let trait_id = self - .lower_trait_ref_from_path(path, self_ty.clone()) - .map(|(trait_ref, _)| trait_ref.hir_trait_id()); - if trait_id == sized_trait { + let trait_id = + self.lower_trait_ref_from_path(path, self_ty.clone()).map(TupleExt::head); + if trait_id.as_ref().map(|trait_ref| trait_ref.hir_trait_id()) == sized_trait { self.unsized_types.insert(self_ty); + clause = trait_id + .and_then(|it| { + Some(TraitRef { + trait_id: to_chalk_trait_id( + LangItem::MetaSized + .resolve_trait(self.db, self.resolver.krate())?, + ), + substitution: it.substitution, + }) + }) + .map(WhereClause::Implemented) + .map(crate::wrap_empty_binders) } } &TypeBound::Lifetime(l) => { @@ -910,6 +922,7 @@ pub(crate) fn field_types_with_diagnostics_query( (Arc::new(res), create_diagnostics(ctx.diagnostics)) } +// FIXME(sized-hierarchy) /// This query exists only to be used when resolving short-hand associated types /// like `T::Item`. /// @@ -1130,6 +1143,7 @@ pub(crate) fn generic_predicates_without_parent_with_diagnostics_query( generic_predicates_filtered_by(db, def, |_, d| d == def) } +// FIXME(sized-hierarchy) /// Resolve the where clause(s) of an item with generics, /// except the ones inherited from the parent fn generic_predicates_filtered_by( @@ -1163,7 +1177,6 @@ where for pred in maybe_parent_generics.where_predicates() { if filter(pred, maybe_parent_generics.def()) { // We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake! - // If we use the parent generics predicates.extend( ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)), ); @@ -1190,6 +1203,7 @@ where ) } +// FIXME(sized-hierarchy) /// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. /// Exception is Self of a trait def. fn implicitly_sized_clauses<'db, 'a, 'subst: 'a>( diff --git a/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/crates/ide-assists/src/handlers/generate_enum_is_method.rs index 3e6d0bec68a6..517906b429a6 100644 --- a/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -1,3 +1,5 @@ +use std::slice; + use ide_db::assists::GroupLabel; use stdx::to_lower_snake_case; use syntax::ast::HasVisibility; @@ -52,7 +54,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_> let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn - let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?; + let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?; let target = variant.syntax().text_range(); acc.add_group( diff --git a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index 3974bcf61875..e4b0f8304976 100644 --- a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -1,3 +1,5 @@ +use std::slice; + use ide_db::assists::GroupLabel; use itertools::Itertools; use stdx::to_lower_snake_case; @@ -148,7 +150,7 @@ fn generate_enum_projection_method( let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text())); // Return early if we've found an existing new fn - let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?; + let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?; let target = variant.syntax().text_range(); acc.add_group( diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs index adc581309d15..1ccd20c25e90 100644 --- a/crates/intern/src/symbol/symbols.rs +++ b/crates/intern/src/symbol/symbols.rs @@ -438,6 +438,8 @@ define_symbols! { shr, simd, sized, + meta_sized, + pointee_sized, skip, slice_len_fn, Some, diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 0dea285e97bd..5cb9bf1c4b00 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -12,7 +12,7 @@ /// Any toolchain less than this version will likely not work with rust-analyzer built from this revision. pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version { major: 1, - minor: 78, + minor: 89, patch: 0, pre: semver::Prerelease::EMPTY, build: semver::BuildMetadata::EMPTY, diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index d13a81d287fa..3396e29157ce 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -77,33 +77,46 @@ pub mod marker { // region:sized + #[lang = "pointee_sized"] + #[fundamental] + #[rustc_specialization_trait] + #[rustc_coinductive] + pub trait PointeeSized {} + + #[lang = "meta_sized"] + #[fundamental] + #[rustc_specialization_trait] + #[rustc_coinductive] + pub trait MetaSized: PointeeSized {} + #[lang = "sized"] #[fundamental] #[rustc_specialization_trait] - pub trait Sized {} + #[rustc_coinductive] + pub trait Sized: MetaSized {} // endregion:sized // region:send pub unsafe auto trait Send {} - impl !Send for *const T {} - impl !Send for *mut T {} + impl !Send for *const T {} + impl !Send for *mut T {} // region:sync - unsafe impl Send for &T {} - unsafe impl Send for &mut T {} + unsafe impl Send for &T {} + unsafe impl Send for &mut T {} // endregion:sync // endregion:send // region:sync pub unsafe auto trait Sync {} - impl !Sync for *const T {} - impl !Sync for *mut T {} + impl !Sync for *const T {} + impl !Sync for *mut T {} // endregion:sync // region:unsize #[lang = "unsize"] - pub trait Unsize {} + pub trait Unsize: PointeeSized {} // endregion:unsize // region:unpin @@ -137,9 +150,9 @@ pub mod marker { bool char } - impl Copy for *const T {} - impl Copy for *mut T {} - impl Copy for &T {} + impl Copy for *const T {} + impl Copy for *mut T {} + impl Copy for &T {} impl Copy for ! {} } // endregion:copy @@ -151,7 +164,7 @@ pub mod marker { // region:phantom_data #[lang = "phantom_data"] - pub struct PhantomData; + pub struct PhantomData; // endregion:phantom_data // region:discriminant @@ -208,7 +221,7 @@ pub mod default { pub mod hash { pub trait Hasher {} - pub trait Hash { + pub trait Hash: PointeeSized { fn hash(&self, state: &mut H); } @@ -224,7 +237,7 @@ pub mod cell { use crate::mem; #[lang = "unsafe_cell"] - pub struct UnsafeCell { + pub struct UnsafeCell { value: T, } @@ -238,7 +251,7 @@ pub mod cell { } } - pub struct Cell { + pub struct Cell { value: UnsafeCell, } @@ -357,7 +370,7 @@ pub mod convert { // endregion:from // region:as_ref - pub trait AsRef { + pub trait AsRef: PointeeSized { fn as_ref(&self) -> &T; } // endregion:as_ref @@ -370,7 +383,7 @@ pub mod mem { // region:manually_drop #[lang = "manually_drop"] #[repr(transparent)] - pub struct ManuallyDrop { + pub struct ManuallyDrop { value: T, } @@ -381,7 +394,7 @@ pub mod mem { } // region:deref - impl crate::ops::Deref for ManuallyDrop { + impl crate::ops::Deref for ManuallyDrop { type Target = T; fn deref(&self) -> &T { &self.value @@ -428,7 +441,7 @@ pub mod mem { pub mod ptr { // region:drop #[lang = "drop_in_place"] - pub unsafe fn drop_in_place(to_drop: *mut T) { + pub unsafe fn drop_in_place(to_drop: *mut T) { unsafe { drop_in_place(to_drop) } } pub const unsafe fn read(src: *const T) -> T { @@ -444,7 +457,7 @@ pub mod ptr { // region:pointee #[lang = "pointee_trait"] #[rustc_deny_explicit_impl(implement_via_object = false)] - pub trait Pointee { + pub trait Pointee: PointeeSized { #[lang = "metadata_type"] type Metadata: Copy + Send + Sync + Ord + Hash + Unpin; } @@ -452,11 +465,11 @@ pub mod ptr { // region:non_null #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] - pub struct NonNull { + pub struct NonNull { pointer: *const T, } // region:coerce_unsized - impl crate::ops::CoerceUnsized> for NonNull where + impl crate::ops::CoerceUnsized> for NonNull where T: crate::marker::Unsize { } @@ -481,19 +494,19 @@ pub mod ops { use crate::marker::Unsize; #[lang = "coerce_unsized"] - pub trait CoerceUnsized {} + pub trait CoerceUnsized {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} - impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {} + impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {} - impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} - impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} - impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} - impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} + impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} + impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} + impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} } pub use self::unsize::CoerceUnsized; // endregion:coerce_unsized @@ -501,19 +514,19 @@ pub mod ops { // region:deref mod deref { #[lang = "deref"] - pub trait Deref { + pub trait Deref: PointeeSized { #[lang = "deref_target"] type Target: ?Sized; fn deref(&self) -> &Self::Target; } - impl Deref for &T { + impl Deref for &T { type Target = T; fn deref(&self) -> &T { loop {} } } - impl Deref for &mut T { + impl Deref for &mut T { type Target = T; fn deref(&self) -> &T { loop {} @@ -521,19 +534,19 @@ pub mod ops { } // region:deref_mut #[lang = "deref_mut"] - pub trait DerefMut: Deref { + pub trait DerefMut: Deref + PointeeSized { fn deref_mut(&mut self) -> &mut Self::Target; } // endregion:deref_mut // region:receiver #[lang = "receiver"] - pub trait Receiver { + pub trait Receiver: PointeeSized { #[lang = "receiver_target"] type Target: ?Sized; } - impl Receiver for P + impl Receiver for P where P: Deref, { @@ -1011,13 +1024,13 @@ pub mod ops { #[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {} - impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} + impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {} - impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} + impl, U: PointeeSized> DispatchFromDyn<*const U> for *const T {} - impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} + impl, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {} } pub use self::dispatch_from_dyn::DispatchFromDyn; // endregion:dispatch_from_dyn @@ -1026,14 +1039,14 @@ pub mod ops { // region:eq pub mod cmp { #[lang = "eq"] - pub trait PartialEq { + pub trait PartialEq: PointeeSized { fn eq(&self, other: &Rhs) -> bool; fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } } - pub trait Eq: PartialEq {} + pub trait Eq: PartialEq + PointeeSized {} // region:derive #[rustc_builtin_macro] @@ -1044,11 +1057,11 @@ pub mod cmp { // region:ord #[lang = "partial_ord"] - pub trait PartialOrd: PartialEq { + pub trait PartialOrd: PartialEq + PointeeSized { fn partial_cmp(&self, other: &Rhs) -> Option; } - pub trait Ord: Eq + PartialOrd { + pub trait Ord: Eq + PartialOrd + PointeeSized { fn cmp(&self, other: &Self) -> Ordering; } @@ -1106,10 +1119,10 @@ pub mod fmt { } } - pub trait Debug { + pub trait Debug: PointeeSized { fn fmt(&self, f: &mut Formatter<'_>) -> Result; } - pub trait Display { + pub trait Display: PointeeSized { fn fmt(&self, f: &mut Formatter<'_>) -> Result; } @@ -1268,7 +1281,7 @@ pub mod fmt { } } - impl Debug for &T { + impl Debug for &T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { (&**self).fmt(f) } @@ -1543,7 +1556,7 @@ pub mod iter { } // endregion:iterators } - impl Iterator for &mut I { + impl Iterator for &mut I { type Item = I::Item; fn next(&mut self) -> Option { (**self).next()