Skip to content

Commit 5f2486e

Browse files
committed
Handle impl ?Sized. Fix tests.
1 parent 421979b commit 5f2486e

File tree

5 files changed

+352
-330
lines changed

5 files changed

+352
-330
lines changed

crates/hir/src/display.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ impl HirDisplay for TypeParam {
239239
let predicates =
240240
bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>();
241241
if !(predicates.is_empty() || f.omit_verbose_types()) {
242-
write_bounds_like_dyn_trait_with_prefix(":", &predicates, SizedByDefault::Sized, f)?;
242+
let default_sized = SizedByDefault::Sized { anchor: self.module(f.db).krate().id };
243+
write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
243244
}
244245
Ok(())
245246
}

crates/hir_ty/src/display.rs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
use std::fmt::{self, Debug};
66

7+
use base_db::CrateId;
78
use chalk_ir::BoundVar;
89
use hir_def::{
910
body,
@@ -15,7 +16,7 @@ use hir_def::{
1516
path::{Path, PathKind},
1617
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
1718
visibility::Visibility,
18-
AssocContainerId, Lookup, ModuleId, TraitId,
19+
AssocContainerId, HasModule, Lookup, ModuleId, TraitId,
1920
};
2021
use hir_expand::{hygiene::Hygiene, name::Name};
2122
use itertools::Itertools;
@@ -582,10 +583,11 @@ impl HirDisplay for Ty {
582583
.as_ref()
583584
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
584585
let bounds = data.substitute(&Interner, &parameters);
586+
let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
585587
write_bounds_like_dyn_trait_with_prefix(
586588
"impl",
587589
bounds.skip_binders(),
588-
SizedByDefault::Sized,
590+
SizedByDefault::Sized { anchor: krate },
589591
f,
590592
)?;
591593
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
@@ -646,10 +648,11 @@ impl HirDisplay for Ty {
646648
_ => false,
647649
})
648650
.collect::<Vec<_>>();
651+
let krate = id.parent.module(f.db.upcast()).krate();
649652
write_bounds_like_dyn_trait_with_prefix(
650653
"impl",
651654
&bounds,
652-
SizedByDefault::Sized,
655+
SizedByDefault::Sized { anchor: krate },
653656
f,
654657
)?;
655658
}
@@ -675,10 +678,11 @@ impl HirDisplay for Ty {
675678
.as_ref()
676679
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
677680
let bounds = data.substitute(&Interner, &opaque_ty.substitution);
681+
let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
678682
write_bounds_like_dyn_trait_with_prefix(
679683
"impl",
680684
bounds.skip_binders(),
681-
SizedByDefault::Sized,
685+
SizedByDefault::Sized { anchor: krate },
682686
f,
683687
)?;
684688
}
@@ -729,17 +733,23 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
729733
utils::fn_traits(db, krate)
730734
}
731735

732-
fn is_sized_trait(db: &dyn DefDatabase, trait_: TraitId) -> Option<bool> {
733-
let krate = trait_.lookup(db).container.krate();
734-
let sized_trait =
735-
db.lang_item(krate, "sized".into()).and_then(|lang_item| lang_item.as_trait())?;
736-
Some(trait_ == sized_trait)
737-
}
738-
739736
#[derive(Clone, Copy, PartialEq, Eq)]
740737
pub enum SizedByDefault {
741738
NotSized,
742-
Sized,
739+
Sized { anchor: CrateId },
740+
}
741+
742+
impl SizedByDefault {
743+
fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
744+
match self {
745+
Self::NotSized => false,
746+
Self::Sized { anchor } => {
747+
let sized_trait =
748+
db.lang_item(anchor, "sized".into()).and_then(|lang_item| lang_item.as_trait());
749+
Some(trait_) == sized_trait
750+
}
751+
}
752+
}
743753
}
744754

745755
pub fn write_bounds_like_dyn_trait_with_prefix(
@@ -749,7 +759,9 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
749759
f: &mut HirFormatter,
750760
) -> Result<(), HirDisplayError> {
751761
write!(f, "{}", prefix)?;
752-
if !predicates.is_empty() {
762+
if !predicates.is_empty()
763+
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
764+
{
753765
write!(f, " ")?;
754766
write_bounds_like_dyn_trait(predicates, default_sized, f)
755767
} else {
@@ -771,22 +783,18 @@ fn write_bounds_like_dyn_trait(
771783
let mut first = true;
772784
let mut angle_open = false;
773785
let mut is_fn_trait = false;
774-
let mut is_sized = None;
786+
let mut is_sized = false;
775787
for p in predicates.iter() {
776788
match p.skip_binders() {
777789
WhereClause::Implemented(trait_ref) => {
778790
let trait_ = trait_ref.hir_trait_id();
779-
match is_sized_trait(f.db.upcast(), trait_) {
780-
Some(true) => {
781-
is_sized = Some(true);
782-
if default_sized == SizedByDefault::Sized {
791+
if default_sized.is_sized_trait(trait_, f.db.upcast()) {
792+
is_sized = true;
793+
if matches!(default_sized, SizedByDefault::Sized { .. }) {
783794
// Don't print +Sized, but rather +?Sized if absent.
784795
continue;
785796
}
786797
}
787-
Some(false) => is_sized = is_sized.or(Some(false)),
788-
None => (),
789-
}
790798
if !is_fn_trait {
791799
is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
792800
}
@@ -851,8 +859,8 @@ fn write_bounds_like_dyn_trait(
851859
if angle_open {
852860
write!(f, ">")?;
853861
}
854-
if default_sized == SizedByDefault::Sized && is_sized.is_some() {
855-
if is_sized == Some(false) {
862+
if matches!(default_sized, SizedByDefault::Sized { .. }) {
863+
if !is_sized {
856864
write!(f, "{}?Sized", if first { "" } else { " + " })?;
857865
} else if first {
858866
write!(f, "Sized")?;

crates/hir_ty/src/tests/display_source_code.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,16 @@ fn main() {
4242

4343
#[test]
4444
fn render_raw_ptr_impl_ty() {
45+
// FIXME: remove parens, they apper because there is an implicit Sized bound
4546
check_types_source_code(
4647
r#"
47-
trait Sized {}
48+
#[lang = "sized"] trait Sized {}
4849
trait Unpin {}
49-
fn foo() -> *const (impl Unpin + Sized) { loop {} }
50+
fn foo() -> *const impl Unpin { loop {} }
5051
fn main() {
5152
let foo = foo();
5253
foo;
53-
} //^^^ *const (impl Unpin + Sized)
54+
} //^^^ *const (impl Unpin)
5455
"#,
5556
);
5657
}
@@ -72,8 +73,7 @@ fn foo(foo: &dyn for<'a> Foo<'a>) {}
7273
fn sized_bounds_apit() {
7374
check_types_source_code(
7475
r#"
75-
#[lang = "sized"]
76-
pub trait Sized {}
76+
#[lang = "sized"] trait Sized {}
7777
7878
trait Foo {}
7979
trait Bar<T> {}
@@ -83,7 +83,7 @@ fn test(
8383
b: impl Foo + Sized,
8484
c: &(impl Foo + ?Sized),
8585
d: S<impl Foo>,
86-
e: impl Bar<impl Foo>,
86+
ref_any: &impl ?Sized,
8787
empty: impl,
8888
) {
8989
a;
@@ -94,8 +94,8 @@ fn test(
9494
//^ &impl Foo + ?Sized
9595
d;
9696
//^ S<impl Foo>
97-
e;
98-
//^ impl Bar<impl Foo>
97+
ref_any;
98+
//^ &impl ?Sized
9999
empty;
100100
} //^ impl Sized
101101
"#,
@@ -106,8 +106,7 @@ fn test(
106106
fn sized_bounds_rpit() {
107107
check_types_source_code(
108108
r#"
109-
#[lang = "sized"]
110-
pub trait Sized {}
109+
#[lang = "sized"] trait Sized {}
111110
112111
trait Foo {}
113112
fn foo() -> impl Foo { loop {} }
@@ -123,8 +122,7 @@ fn test<T: Foo>() {
123122
fn sized_bounds_impl_traits_in_fn_signature() {
124123
check_types_source_code(
125124
r#"
126-
#[lang = "sized"]
127-
pub trait Sized {}
125+
#[lang = "sized"] trait Sized {}
128126
129127
trait Foo {}
130128
fn test(

crates/hir_ty/src/tests/method_resolution.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ fn test() { foo.call(); }
922922
fn super_trait_impl_return_trait_method_resolution() {
923923
check_infer(
924924
r#"
925+
#[lang = "sized"] trait Sized {}
925926
trait Base {
926927
fn foo(self) -> usize;
927928
}
@@ -939,26 +940,26 @@ fn super_trait_impl_return_trait_method_resolution() {
939940
}
940941
"#,
941942
expect![[r#"
942-
24..28 'self': Self
943-
90..101 '{ loop {} }': !
944-
92..99 'loop {}': !
945-
97..99 '{}': ()
946-
128..139 '{ loop {} }': !
947-
130..137 'loop {}': !
948-
135..137 '{}': ()
949-
149..154 'base2': impl Base
950-
167..173 'super2': impl Super
951-
187..264 '{ ...o(); }': ()
952-
193..198 'base1': fn base1() -> impl Base
953-
193..200 'base1()': impl Base
954-
193..206 'base1().foo()': usize
955-
212..218 'super1': fn super1() -> impl Super
956-
212..220 'super1()': impl Super
957-
212..226 'super1().foo()': usize
958-
232..237 'base2': impl Base
959-
232..243 'base2.foo()': usize
960-
249..255 'super2': impl Super
961-
249..261 'super2.foo()': usize
943+
57..61 'self': Self
944+
123..134 '{ loop {} }': !
945+
125..132 'loop {}': !
946+
130..132 '{}': ()
947+
161..172 '{ loop {} }': !
948+
163..170 'loop {}': !
949+
168..170 '{}': ()
950+
182..187 'base2': impl Base
951+
200..206 'super2': impl Super
952+
220..297 '{ ...o(); }': ()
953+
226..231 'base1': fn base1() -> impl Base
954+
226..233 'base1()': impl Base
955+
226..239 'base1().foo()': usize
956+
245..251 'super1': fn super1() -> impl Super
957+
245..253 'super1()': impl Super
958+
245..259 'super1().foo()': usize
959+
265..270 'base2': impl Base
960+
265..276 'base2.foo()': usize
961+
282..288 'super2': impl Super
962+
282..294 'super2.foo()': usize
962963
"#]],
963964
);
964965
}

0 commit comments

Comments
 (0)