mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
add implicit Sized bound to associated types
This commit is contained in:
parent
8f2a040d10
commit
b217e9cc50
4 changed files with 79 additions and 5 deletions
|
@ -412,13 +412,28 @@ pub(crate) fn associated_ty_data_query(
|
||||||
.with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
|
.with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
|
||||||
let self_ty =
|
let self_ty =
|
||||||
TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
|
TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
|
||||||
let bounds = type_alias_data
|
let mut bounds: Vec<_> = type_alias_data
|
||||||
.bounds
|
.bounds
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
|
.flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
|
||||||
.filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
|
.filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if !ctx.unsized_types.borrow().contains(&self_ty) {
|
||||||
|
let sized_trait = resolver
|
||||||
|
.krate()
|
||||||
|
.and_then(|krate| db.lang_item(krate, "sized".into()))
|
||||||
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
||||||
|
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
|
||||||
|
let trait_bound =
|
||||||
|
rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };
|
||||||
|
let inline_bound = rust_ir::InlineBound::TraitBound(trait_bound);
|
||||||
|
chalk_ir::Binders::empty(&Interner, inline_bound)
|
||||||
|
});
|
||||||
|
bounds.extend(sized_bound);
|
||||||
|
bounds.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Re-enable where clauses on associated types when an upstream chalk bug is fixed.
|
// FIXME: Re-enable where clauses on associated types when an upstream chalk bug is fixed.
|
||||||
// (rust-analyzer#9052)
|
// (rust-analyzer#9052)
|
||||||
// let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
|
// let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
|
||||||
|
|
|
@ -66,8 +66,8 @@ pub struct TyLoweringContext<'a> {
|
||||||
/// Splitting this up would be a possible fix.
|
/// Splitting this up would be a possible fix.
|
||||||
opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>,
|
opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>,
|
||||||
expander: RefCell<Option<Expander>>,
|
expander: RefCell<Option<Expander>>,
|
||||||
/// Keeps tracking types with explicit `?Sized` bounds.
|
/// Tracks types with explicit `?Sized` bounds.
|
||||||
unsized_types: RefCell<FxHashSet<Ty>>,
|
pub(crate) unsized_types: RefCell<FxHashSet<Ty>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TyLoweringContext<'a> {
|
impl<'a> TyLoweringContext<'a> {
|
||||||
|
@ -796,7 +796,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
.and_then(|krate| self.db.lang_item(krate, "sized".into()))
|
.and_then(|krate| self.db.lang_item(krate, "sized".into()))
|
||||||
.and_then(|lang_item| lang_item.as_trait());
|
.and_then(|lang_item| lang_item.as_trait());
|
||||||
// Don't lower associated type bindings as the only possible relaxed trait bound
|
// Don't lower associated type bindings as the only possible relaxed trait bound
|
||||||
// `?Sized` has none of them.
|
// `?Sized` has no of them.
|
||||||
// If we got another trait here ignore the bound completely.
|
// If we got another trait here ignore the bound completely.
|
||||||
let trait_id = self
|
let trait_id = self
|
||||||
.lower_trait_ref_from_path(path, Some(self_ty.clone()))
|
.lower_trait_ref_from_path(path, Some(self_ty.clone()))
|
||||||
|
@ -996,7 +996,6 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
let ctx =
|
let ctx =
|
||||||
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
|
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
let generics = generics(db.upcast(), param_id.parent);
|
let generics = generics(db.upcast(), param_id.parent);
|
||||||
// TODO(iDawer): add implicitly sized clauses?
|
|
||||||
resolver
|
resolver
|
||||||
.where_predicates_in_scope()
|
.where_predicates_in_scope()
|
||||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
// we have to filter out all other predicates *first*, before attempting to lower them
|
||||||
|
|
|
@ -1312,3 +1312,31 @@ impl<'a, T> IntoIterator for &'a [T] {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sized_blanket_impl() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized {}
|
||||||
|
|
||||||
|
trait Foo { fn foo() -> u8; }
|
||||||
|
impl<T: Sized> Foo for T {}
|
||||||
|
fn f<S: Sized, T, U: ?Sized>() {
|
||||||
|
u32::foo;
|
||||||
|
S::foo;
|
||||||
|
T::foo;
|
||||||
|
U::foo;
|
||||||
|
<[u32]>::foo;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
127..198 '{ ...foo; }': ()
|
||||||
|
133..141 'u32::foo': fn foo<u32>() -> u8
|
||||||
|
147..153 'S::foo': fn foo<S>() -> u8
|
||||||
|
159..165 'T::foo': fn foo<T>() -> u8
|
||||||
|
171..177 'U::foo': {unknown}
|
||||||
|
183..195 '<[u32]>::foo': {unknown}
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -3515,3 +3515,35 @@ fn test() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn associated_type_sized_bounds() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized {}
|
||||||
|
|
||||||
|
struct Yes;
|
||||||
|
trait IsSized { const IS_SIZED: Yes; }
|
||||||
|
impl<T: Sized> IsSized for T { const IS_SIZED: Yes = Yes; }
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type Explicit: Sized;
|
||||||
|
type Implicit;
|
||||||
|
type Relaxed: ?Sized;
|
||||||
|
}
|
||||||
|
fn f<F: Foo>() {
|
||||||
|
F::Explicit::IS_SIZED;
|
||||||
|
F::Implicit::IS_SIZED;
|
||||||
|
F::Relaxed::IS_SIZED;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
142..145 'Yes': Yes
|
||||||
|
250..333 '{ ...ZED; }': ()
|
||||||
|
256..277 'F::Exp..._SIZED': Yes
|
||||||
|
283..304 'F::Imp..._SIZED': Yes
|
||||||
|
310..330 'F::Rel..._SIZED': {unknown}
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue