Merge #7732
7732: Don't lower TypeBound::Lifetime as GenericPredicate::Error r=flodiebold a=Veykril
Basically we just discard the typebound for now instead when lowering to `GenericPredicate`. I think this shouldn't have any other side effects?
Fixes #7683(hopefully for real this time)
I also played around with introducing `GenericPredicate::LifetimeOutlives` and `GenericPredicate::TypeOutlives`(see b9d6904845) but that won't fix this issue(at least not for now) due to lifetime predicate mismatches when resolving methods so I figure this is a good way to fix it for now.
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
@@ -28,7 +28,7 @@ use hir_expand::{
|
|||||||
};
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
autoderef,
|
autoderef,
|
||||||
display::{write_bounds_like_dyn_trait, HirDisplayError, HirFormatter},
|
display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
|
||||||
method_resolution,
|
method_resolution,
|
||||||
traits::{FnTrait, Solution, SolutionVariables},
|
traits::{FnTrait, Solution, SolutionVariables},
|
||||||
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
|
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
|
||||||
@@ -1379,8 +1379,7 @@ impl HirDisplay for TypeParam {
|
|||||||
let substs = Substs::type_params(f.db, self.id.parent);
|
let substs = Substs::type_params(f.db, self.id.parent);
|
||||||
let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
|
let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
|
||||||
if !(predicates.is_empty() || f.omit_verbose_types()) {
|
if !(predicates.is_empty() || f.omit_verbose_types()) {
|
||||||
write!(f, ": ")?;
|
write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
|
||||||
write_bounds_like_dyn_trait(&predicates, f)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,8 +467,7 @@ impl HirDisplay for ApplicationTy {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
|
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
|
||||||
let bounds = data.subst(&self.parameters);
|
let bounds = data.subst(&self.parameters);
|
||||||
write!(f, "impl ")?;
|
write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
|
||||||
write_bounds_like_dyn_trait(&bounds.value, f)?;
|
|
||||||
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
|
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
|
||||||
}
|
}
|
||||||
OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
|
OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
|
||||||
@@ -548,10 +547,10 @@ impl HirDisplay for Ty {
|
|||||||
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
||||||
}
|
}
|
||||||
TypeParamProvenance::ArgumentImplTrait => {
|
TypeParamProvenance::ArgumentImplTrait => {
|
||||||
write!(f, "impl ")?;
|
|
||||||
let bounds = f.db.generic_predicates_for_param(*id);
|
let bounds = f.db.generic_predicates_for_param(*id);
|
||||||
let substs = Substs::type_params_for_generics(&generics);
|
let substs = Substs::type_params_for_generics(&generics);
|
||||||
write_bounds_like_dyn_trait(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
|
"impl",
|
||||||
&bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
|
&bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
|
||||||
f,
|
f,
|
||||||
)?;
|
)?;
|
||||||
@@ -560,8 +559,7 @@ impl HirDisplay for Ty {
|
|||||||
}
|
}
|
||||||
Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
|
Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
|
||||||
Ty::Dyn(predicates) => {
|
Ty::Dyn(predicates) => {
|
||||||
write!(f, "dyn ")?;
|
write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
|
||||||
write_bounds_like_dyn_trait(predicates, f)?;
|
|
||||||
}
|
}
|
||||||
Ty::Opaque(opaque_ty) => {
|
Ty::Opaque(opaque_ty) => {
|
||||||
match opaque_ty.opaque_ty_id {
|
match opaque_ty.opaque_ty_id {
|
||||||
@@ -572,8 +570,7 @@ impl HirDisplay for Ty {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
|
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
|
||||||
let bounds = data.subst(&opaque_ty.parameters);
|
let bounds = data.subst(&opaque_ty.parameters);
|
||||||
write!(f, "impl ")?;
|
write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
|
||||||
write_bounds_like_dyn_trait(&bounds.value, f)?;
|
|
||||||
}
|
}
|
||||||
OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
|
OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
|
||||||
write!(f, "{{async block}}")?;
|
write!(f, "{{async block}}")?;
|
||||||
@@ -627,7 +624,21 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
|
|||||||
ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
|
ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_bounds_like_dyn_trait(
|
pub fn write_bounds_like_dyn_trait_with_prefix(
|
||||||
|
prefix: &str,
|
||||||
|
predicates: &[GenericPredicate],
|
||||||
|
f: &mut HirFormatter,
|
||||||
|
) -> Result<(), HirDisplayError> {
|
||||||
|
write!(f, "{}", prefix)?;
|
||||||
|
if !predicates.is_empty() {
|
||||||
|
write!(f, " ")?;
|
||||||
|
write_bounds_like_dyn_trait(predicates, f)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_bounds_like_dyn_trait(
|
||||||
predicates: &[GenericPredicate],
|
predicates: &[GenericPredicate],
|
||||||
f: &mut HirFormatter,
|
f: &mut HirFormatter,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
|
|||||||
@@ -655,17 +655,6 @@ impl TraitRef {
|
|||||||
) -> Substs {
|
) -> Substs {
|
||||||
substs_from_path_segment(ctx, segment, Some(resolved.into()), false)
|
substs_from_path_segment(ctx, segment, Some(resolved.into()), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_type_bound(
|
|
||||||
ctx: &TyLoweringContext<'_>,
|
|
||||||
bound: &TypeBound,
|
|
||||||
self_ty: Ty,
|
|
||||||
) -> Option<TraitRef> {
|
|
||||||
match bound {
|
|
||||||
TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)),
|
|
||||||
TypeBound::Lifetime(_) | TypeBound::Error => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericPredicate {
|
impl GenericPredicate {
|
||||||
@@ -705,10 +694,19 @@ impl GenericPredicate {
|
|||||||
bound: &'a TypeBound,
|
bound: &'a TypeBound,
|
||||||
self_ty: Ty,
|
self_ty: Ty,
|
||||||
) -> impl Iterator<Item = GenericPredicate> + 'a {
|
) -> impl Iterator<Item = GenericPredicate> + 'a {
|
||||||
let trait_ref = TraitRef::from_type_bound(ctx, bound, self_ty);
|
let mut bindings = None;
|
||||||
iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented))
|
let trait_ref = match bound {
|
||||||
.chain(
|
TypeBound::Path(path) => {
|
||||||
trait_ref
|
bindings = TraitRef::from_path(ctx, path, Some(self_ty));
|
||||||
|
Some(
|
||||||
|
bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TypeBound::Lifetime(_) => None,
|
||||||
|
TypeBound::Error => Some(GenericPredicate::Error),
|
||||||
|
};
|
||||||
|
trait_ref.into_iter().chain(
|
||||||
|
bindings
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)),
|
.flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1114,14 +1114,14 @@ fn method_on_dyn_impl() {
|
|||||||
trait Foo {}
|
trait Foo {}
|
||||||
|
|
||||||
impl Foo for u32 {}
|
impl Foo for u32 {}
|
||||||
impl dyn Foo {
|
impl dyn Foo + '_ {
|
||||||
pub fn dyn_foo(&self) -> u32 {
|
pub fn dyn_foo(&self) -> u32 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let f = &42u32 as &dyn Foo<u32>;
|
let f = &42u32 as &dyn Foo;
|
||||||
f.dyn_foo();
|
f.dyn_foo();
|
||||||
// ^u32
|
// ^u32
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1409,10 +1409,10 @@ fn weird_bounds() {
|
|||||||
fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {}
|
fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
23..24 'a': impl Trait + {error}
|
23..24 'a': impl Trait
|
||||||
50..51 'b': impl {error}
|
50..51 'b': impl
|
||||||
69..70 'c': impl Trait
|
69..70 'c': impl Trait
|
||||||
86..87 'd': impl {error}
|
86..87 'd': impl
|
||||||
107..108 'e': impl {error}
|
107..108 'e': impl {error}
|
||||||
123..124 'f': impl Trait + {error}
|
123..124 'f': impl Trait + {error}
|
||||||
147..149 '{}': ()
|
147..149 '{}': ()
|
||||||
|
|||||||
@@ -3417,7 +3417,7 @@ impl<T> Foo<T$0> {}
|
|||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
// lifetimes aren't being substituted yet
|
// lifetimes bounds arent being tracked yet
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
struct Foo<T>(T);
|
struct Foo<T>(T);
|
||||||
@@ -3427,7 +3427,7 @@ impl<T: 'static> Foo<T$0> {}
|
|||||||
*T*
|
*T*
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
T: {error}
|
T
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user