Handle impl ?Sized. Fix tests.

This commit is contained in:
Dawer 2021-06-15 23:28:37 +05:00
parent 421979bc68
commit 5f2486e9a8
5 changed files with 352 additions and 330 deletions

View file

@ -239,7 +239,8 @@ impl HirDisplay for TypeParam {
let predicates = let predicates =
bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>(); bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>();
if !(predicates.is_empty() || f.omit_verbose_types()) { if !(predicates.is_empty() || f.omit_verbose_types()) {
write_bounds_like_dyn_trait_with_prefix(":", &predicates, SizedByDefault::Sized, f)?; let default_sized = SizedByDefault::Sized { anchor: self.module(f.db).krate().id };
write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
} }
Ok(()) Ok(())
} }

View file

@ -4,6 +4,7 @@
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use base_db::CrateId;
use chalk_ir::BoundVar; use chalk_ir::BoundVar;
use hir_def::{ use hir_def::{
body, body,
@ -15,7 +16,7 @@ use hir_def::{
path::{Path, PathKind}, path::{Path, PathKind},
type_ref::{TraitBoundModifier, TypeBound, TypeRef}, type_ref::{TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility, visibility::Visibility,
AssocContainerId, Lookup, ModuleId, TraitId, AssocContainerId, HasModule, Lookup, ModuleId, TraitId,
}; };
use hir_expand::{hygiene::Hygiene, name::Name}; use hir_expand::{hygiene::Hygiene, name::Name};
use itertools::Itertools; use itertools::Itertools;
@ -582,10 +583,11 @@ 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.substitute(&Interner, &parameters); let bounds = data.substitute(&Interner, &parameters);
let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix(
"impl", "impl",
bounds.skip_binders(), bounds.skip_binders(),
SizedByDefault::Sized, SizedByDefault::Sized { anchor: krate },
f, 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
@ -646,10 +648,11 @@ impl HirDisplay for Ty {
_ => false, _ => false,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let krate = id.parent.module(f.db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix(
"impl", "impl",
&bounds, &bounds,
SizedByDefault::Sized, SizedByDefault::Sized { anchor: krate },
f, f,
)?; )?;
} }
@ -675,10 +678,11 @@ 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.substitute(&Interner, &opaque_ty.substitution); let bounds = data.substitute(&Interner, &opaque_ty.substitution);
let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix(
"impl", "impl",
bounds.skip_binders(), bounds.skip_binders(),
SizedByDefault::Sized, SizedByDefault::Sized { anchor: krate },
f, f,
)?; )?;
} }
@ -729,17 +733,23 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
utils::fn_traits(db, krate) utils::fn_traits(db, krate)
} }
fn is_sized_trait(db: &dyn DefDatabase, trait_: TraitId) -> Option<bool> {
let krate = trait_.lookup(db).container.krate();
let sized_trait =
db.lang_item(krate, "sized".into()).and_then(|lang_item| lang_item.as_trait())?;
Some(trait_ == sized_trait)
}
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
pub enum SizedByDefault { pub enum SizedByDefault {
NotSized, NotSized,
Sized, Sized { anchor: CrateId },
}
impl SizedByDefault {
fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
match self {
Self::NotSized => false,
Self::Sized { anchor } => {
let sized_trait =
db.lang_item(anchor, "sized".into()).and_then(|lang_item| lang_item.as_trait());
Some(trait_) == sized_trait
}
}
}
} }
pub fn write_bounds_like_dyn_trait_with_prefix( pub fn write_bounds_like_dyn_trait_with_prefix(
@ -749,7 +759,9 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
f: &mut HirFormatter, f: &mut HirFormatter,
) -> Result<(), HirDisplayError> { ) -> Result<(), HirDisplayError> {
write!(f, "{}", prefix)?; write!(f, "{}", prefix)?;
if !predicates.is_empty() { if !predicates.is_empty()
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
{
write!(f, " ")?; write!(f, " ")?;
write_bounds_like_dyn_trait(predicates, default_sized, f) write_bounds_like_dyn_trait(predicates, default_sized, f)
} else { } else {
@ -771,22 +783,18 @@ fn write_bounds_like_dyn_trait(
let mut first = true; let mut first = true;
let mut angle_open = false; let mut angle_open = false;
let mut is_fn_trait = false; let mut is_fn_trait = false;
let mut is_sized = None; let mut is_sized = false;
for p in predicates.iter() { for p in predicates.iter() {
match p.skip_binders() { match p.skip_binders() {
WhereClause::Implemented(trait_ref) => { WhereClause::Implemented(trait_ref) => {
let trait_ = trait_ref.hir_trait_id(); let trait_ = trait_ref.hir_trait_id();
match is_sized_trait(f.db.upcast(), trait_) { if default_sized.is_sized_trait(trait_, f.db.upcast()) {
Some(true) => { is_sized = true;
is_sized = Some(true); if matches!(default_sized, SizedByDefault::Sized { .. }) {
if default_sized == SizedByDefault::Sized {
// Don't print +Sized, but rather +?Sized if absent. // Don't print +Sized, but rather +?Sized if absent.
continue; continue;
} }
} }
Some(false) => is_sized = is_sized.or(Some(false)),
None => (),
}
if !is_fn_trait { if !is_fn_trait {
is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
} }
@ -851,8 +859,8 @@ fn write_bounds_like_dyn_trait(
if angle_open { if angle_open {
write!(f, ">")?; write!(f, ">")?;
} }
if default_sized == SizedByDefault::Sized && is_sized.is_some() { if matches!(default_sized, SizedByDefault::Sized { .. }) {
if is_sized == Some(false) { if !is_sized {
write!(f, "{}?Sized", if first { "" } else { " + " })?; write!(f, "{}?Sized", if first { "" } else { " + " })?;
} else if first { } else if first {
write!(f, "Sized")?; write!(f, "Sized")?;

View file

@ -42,15 +42,16 @@ fn main() {
#[test] #[test]
fn render_raw_ptr_impl_ty() { fn render_raw_ptr_impl_ty() {
// FIXME: remove parens, they apper because there is an implicit Sized bound
check_types_source_code( check_types_source_code(
r#" r#"
trait Sized {} #[lang = "sized"] trait Sized {}
trait Unpin {} trait Unpin {}
fn foo() -> *const (impl Unpin + Sized) { loop {} } fn foo() -> *const impl Unpin { loop {} }
fn main() { fn main() {
let foo = foo(); let foo = foo();
foo; foo;
} //^^^ *const (impl Unpin + Sized) } //^^^ *const (impl Unpin)
"#, "#,
); );
} }
@ -72,8 +73,7 @@ fn foo(foo: &dyn for<'a> Foo<'a>) {}
fn sized_bounds_apit() { fn sized_bounds_apit() {
check_types_source_code( check_types_source_code(
r#" r#"
#[lang = "sized"] #[lang = "sized"] trait Sized {}
pub trait Sized {}
trait Foo {} trait Foo {}
trait Bar<T> {} trait Bar<T> {}
@ -83,7 +83,7 @@ fn test(
b: impl Foo + Sized, b: impl Foo + Sized,
c: &(impl Foo + ?Sized), c: &(impl Foo + ?Sized),
d: S<impl Foo>, d: S<impl Foo>,
e: impl Bar<impl Foo>, ref_any: &impl ?Sized,
empty: impl, empty: impl,
) { ) {
a; a;
@ -94,8 +94,8 @@ fn test(
//^ &impl Foo + ?Sized //^ &impl Foo + ?Sized
d; d;
//^ S<impl Foo> //^ S<impl Foo>
e; ref_any;
//^ impl Bar<impl Foo> //^ &impl ?Sized
empty; empty;
} //^ impl Sized } //^ impl Sized
"#, "#,
@ -106,8 +106,7 @@ fn test(
fn sized_bounds_rpit() { fn sized_bounds_rpit() {
check_types_source_code( check_types_source_code(
r#" r#"
#[lang = "sized"] #[lang = "sized"] trait Sized {}
pub trait Sized {}
trait Foo {} trait Foo {}
fn foo() -> impl Foo { loop {} } fn foo() -> impl Foo { loop {} }
@ -123,8 +122,7 @@ fn test<T: Foo>() {
fn sized_bounds_impl_traits_in_fn_signature() { fn sized_bounds_impl_traits_in_fn_signature() {
check_types_source_code( check_types_source_code(
r#" r#"
#[lang = "sized"] #[lang = "sized"] trait Sized {}
pub trait Sized {}
trait Foo {} trait Foo {}
fn test( fn test(

View file

@ -922,6 +922,7 @@ fn test() { foo.call(); }
fn super_trait_impl_return_trait_method_resolution() { fn super_trait_impl_return_trait_method_resolution() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Base { trait Base {
fn foo(self) -> usize; fn foo(self) -> usize;
} }
@ -939,26 +940,26 @@ fn super_trait_impl_return_trait_method_resolution() {
} }
"#, "#,
expect![[r#" expect![[r#"
24..28 'self': Self 57..61 'self': Self
90..101 '{ loop {} }': ! 123..134 '{ loop {} }': !
92..99 'loop {}': ! 125..132 'loop {}': !
97..99 '{}': () 130..132 '{}': ()
128..139 '{ loop {} }': ! 161..172 '{ loop {} }': !
130..137 'loop {}': ! 163..170 'loop {}': !
135..137 '{}': () 168..170 '{}': ()
149..154 'base2': impl Base 182..187 'base2': impl Base
167..173 'super2': impl Super 200..206 'super2': impl Super
187..264 '{ ...o(); }': () 220..297 '{ ...o(); }': ()
193..198 'base1': fn base1() -> impl Base 226..231 'base1': fn base1() -> impl Base
193..200 'base1()': impl Base 226..233 'base1()': impl Base
193..206 'base1().foo()': usize 226..239 'base1().foo()': usize
212..218 'super1': fn super1() -> impl Super 245..251 'super1': fn super1() -> impl Super
212..220 'super1()': impl Super 245..253 'super1()': impl Super
212..226 'super1().foo()': usize 245..259 'super1().foo()': usize
232..237 'base2': impl Base 265..270 'base2': impl Base
232..243 'base2.foo()': usize 265..276 'base2.foo()': usize
249..255 'super2': impl Super 282..288 'super2': impl Super
249..261 'super2.foo()': usize 282..294 'super2.foo()': usize
"#]], "#]],
); );
} }

View file

@ -845,6 +845,7 @@ fn test<T: ApplyL>(t: T) {
fn argument_impl_trait() { fn argument_impl_trait() {
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T> { trait Trait<T> {
fn foo(&self) -> T; fn foo(&self) -> T;
fn foo2(&self) -> i64; fn foo2(&self) -> i64;
@ -866,34 +867,34 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
z.foo2(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 62..66 'self': &Self
54..58 'self': &Self 87..91 'self': &Self
77..78 'x': impl Trait<u16> 110..111 'x': impl Trait<u16>
97..99 '{}': () 130..132 '{}': ()
154..155 'x': impl Trait<u64> 187..188 'x': impl Trait<u64>
174..175 'y': &impl Trait<u32> 207..208 'y': &impl Trait<u32>
195..323 '{ ...2(); }': () 228..356 '{ ...2(); }': ()
201..202 'x': impl Trait<u64> 234..235 'x': impl Trait<u64>
208..209 'y': &impl Trait<u32> 241..242 'y': &impl Trait<u32>
219..220 'z': S<u16> 252..253 'z': S<u16>
223..224 'S': S<u16>(u16) -> S<u16> 256..257 'S': S<u16>(u16) -> S<u16>
223..227 'S(1)': S<u16> 256..260 'S(1)': S<u16>
225..226 '1': u16 258..259 '1': u16
233..236 'bar': fn bar(S<u16>) 266..269 'bar': fn bar(S<u16>)
233..239 'bar(z)': () 266..272 'bar(z)': ()
237..238 'z': S<u16> 270..271 'z': S<u16>
245..246 'x': impl Trait<u64> 278..279 'x': impl Trait<u64>
245..252 'x.foo()': u64 278..285 'x.foo()': u64
258..259 'y': &impl Trait<u32> 291..292 'y': &impl Trait<u32>
258..265 'y.foo()': u32 291..298 'y.foo()': u32
271..272 'z': S<u16> 304..305 'z': S<u16>
271..278 'z.foo()': u16 304..311 'z.foo()': u16
284..285 'x': impl Trait<u64> 317..318 'x': impl Trait<u64>
284..292 'x.foo2()': i64 317..325 'x.foo2()': i64
298..299 'y': &impl Trait<u32> 331..332 'y': &impl Trait<u32>
298..306 'y.foo2()': i64 331..339 'y.foo2()': i64
312..313 'z': S<u16> 345..346 'z': S<u16>
312..320 'z.foo2()': i64 345..353 'z.foo2()': i64
"#]], "#]],
); );
} }
@ -902,6 +903,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
fn argument_impl_trait_type_args_1() { fn argument_impl_trait_type_args_1() {
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait {} trait Trait {}
trait Foo { trait Foo {
// this function has an implicit Self param, an explicit type param, // this function has an implicit Self param, an explicit type param,
@ -926,39 +928,39 @@ fn test() {
foo::<u32, i32>(S); // we should ignore the extraneous i32 foo::<u32, i32>(S); // we should ignore the extraneous i32
}"#, }"#,
expect![[r#" expect![[r#"
155..156 'x': impl Trait 188..189 'x': impl Trait
175..186 '{ loop {} }': T 208..219 '{ loop {} }': T
177..184 'loop {}': ! 210..217 'loop {}': !
182..184 '{}': () 215..217 '{}': ()
199..200 'x': impl Trait 232..233 'x': impl Trait
219..230 '{ loop {} }': T 252..263 '{ loop {} }': T
221..228 'loop {}': ! 254..261 'loop {}': !
226..228 '{}': () 259..261 '{}': ()
300..509 '{ ... i32 }': () 333..542 '{ ... i32 }': ()
306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} 339..347 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown}
306..317 'Foo::bar(S)': {unknown} 339..350 'Foo::bar(S)': {unknown}
315..316 'S': S 348..349 'S': S
323..338 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown} 356..371 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown}
323..341 '<F as ...bar(S)': {unknown} 356..374 '<F as ...bar(S)': {unknown}
339..340 'S': S 372..373 'S': S
347..353 'F::bar': fn bar<F, {unknown}>(S) -> {unknown} 380..386 'F::bar': fn bar<F, {unknown}>(S) -> {unknown}
347..356 'F::bar(S)': {unknown} 380..389 'F::bar(S)': {unknown}
354..355 'S': S 387..388 'S': S
362..377 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32 395..410 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32
362..380 'Foo::b...32>(S)': u32 395..413 'Foo::b...32>(S)': u32
378..379 'S': S 411..412 'S': S
386..408 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32 419..441 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32
386..411 '<F as ...32>(S)': u32 419..444 '<F as ...32>(S)': u32
409..410 'S': S 442..443 'S': S
418..421 'foo': fn foo<{unknown}>(S) -> {unknown} 451..454 'foo': fn foo<{unknown}>(S) -> {unknown}
418..424 'foo(S)': {unknown} 451..457 'foo(S)': {unknown}
422..423 'S': S 455..456 'S': S
430..440 'foo::<u32>': fn foo<u32>(S) -> u32 463..473 'foo::<u32>': fn foo<u32>(S) -> u32
430..443 'foo::<u32>(S)': u32 463..476 'foo::<u32>(S)': u32
441..442 'S': S 474..475 'S': S
449..464 'foo::<u32, i32>': fn foo<u32>(S) -> u32 482..497 'foo::<u32, i32>': fn foo<u32>(S) -> u32
449..467 'foo::<...32>(S)': u32 482..500 'foo::<...32>(S)': u32
465..466 'S': S 498..499 'S': S
"#]], "#]],
); );
} }
@ -967,6 +969,7 @@ fn test() {
fn argument_impl_trait_type_args_2() { fn argument_impl_trait_type_args_2() {
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait {} trait Trait {}
struct S; struct S;
impl Trait for S {} impl Trait for S {}
@ -982,24 +985,24 @@ fn test() {
F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
}"#, }"#,
expect![[r#" expect![[r#"
87..91 'self': F<T> 120..124 'self': F<T>
93..94 'x': impl Trait 126..127 'x': impl Trait
118..129 '{ loop {} }': (T, U) 151..162 '{ loop {} }': (T, U)
120..127 'loop {}': ! 153..160 'loop {}': !
125..127 '{}': () 158..160 '{}': ()
143..283 '{ ...ored }': () 176..316 '{ ...ored }': ()
149..150 'F': F<{unknown}> 182..183 'F': F<{unknown}>
149..157 'F.foo(S)': ({unknown}, {unknown}) 182..190 'F.foo(S)': ({unknown}, {unknown})
155..156 'S': S 188..189 'S': S
163..171 'F::<u32>': F<u32> 196..204 'F::<u32>': F<u32>
163..178 'F::<u32>.foo(S)': (u32, {unknown}) 196..211 'F::<u32>.foo(S)': (u32, {unknown})
176..177 'S': S 209..210 'S': S
184..192 'F::<u32>': F<u32> 217..225 'F::<u32>': F<u32>
184..206 'F::<u3...32>(S)': (u32, i32) 217..239 'F::<u3...32>(S)': (u32, i32)
204..205 'S': S
212..220 'F::<u32>': F<u32>
212..239 'F::<u3...32>(S)': (u32, i32)
237..238 'S': S 237..238 'S': S
245..253 'F::<u32>': F<u32>
245..272 'F::<u3...32>(S)': (u32, i32)
270..271 'S': S
"#]], "#]],
); );
} }
@ -1008,6 +1011,7 @@ fn test() {
fn argument_impl_trait_to_fn_pointer() { fn argument_impl_trait_to_fn_pointer() {
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait {} trait Trait {}
fn foo(x: impl Trait) { loop {} } fn foo(x: impl Trait) { loop {} }
struct S; struct S;
@ -1017,13 +1021,13 @@ fn test() {
let f: fn(S) -> () = foo; let f: fn(S) -> () = foo;
}"#, }"#,
expect![[r#" expect![[r#"
22..23 'x': impl Trait 55..56 'x': impl Trait
37..48 '{ loop {} }': () 70..81 '{ loop {} }': ()
39..46 'loop {}': ! 72..79 'loop {}': !
44..46 '{}': () 77..79 '{}': ()
90..123 '{ ...foo; }': () 123..156 '{ ...foo; }': ()
100..101 'f': fn(S) 133..134 'f': fn(S)
117..120 'foo': fn foo(S) 150..153 'foo': fn foo(S)
"#]], "#]],
); );
} }
@ -1032,6 +1036,7 @@ fn test() {
fn impl_trait() { fn impl_trait() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T> { trait Trait<T> {
fn foo(&self) -> T; fn foo(&self) -> T;
fn foo2(&self) -> i64; fn foo2(&self) -> i64;
@ -1050,29 +1055,29 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
z.foo2(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 62..66 'self': &Self
54..58 'self': &Self 87..91 'self': &Self
98..100 '{}': () 131..133 '{}': ()
110..111 'x': impl Trait<u64> 143..144 'x': impl Trait<u64>
130..131 'y': &impl Trait<u64> 163..164 'y': &impl Trait<u64>
151..268 '{ ...2(); }': () 184..301 '{ ...2(); }': ()
157..158 'x': impl Trait<u64>
164..165 'y': &impl Trait<u64>
175..176 'z': impl Trait<u64>
179..182 'bar': fn bar() -> impl Trait<u64>
179..184 'bar()': impl Trait<u64>
190..191 'x': impl Trait<u64> 190..191 'x': impl Trait<u64>
190..197 'x.foo()': u64 197..198 'y': &impl Trait<u64>
203..204 'y': &impl Trait<u64> 208..209 'z': impl Trait<u64>
203..210 'y.foo()': u64 212..215 'bar': fn bar() -> impl Trait<u64>
216..217 'z': impl Trait<u64> 212..217 'bar()': impl Trait<u64>
216..223 'z.foo()': u64 223..224 'x': impl Trait<u64>
229..230 'x': impl Trait<u64> 223..230 'x.foo()': u64
229..237 'x.foo2()': i64 236..237 'y': &impl Trait<u64>
243..244 'y': &impl Trait<u64> 236..243 'y.foo()': u64
243..251 'y.foo2()': i64 249..250 'z': impl Trait<u64>
257..258 'z': impl Trait<u64> 249..256 'z.foo()': u64
257..265 'z.foo2()': i64 262..263 'x': impl Trait<u64>
262..270 'x.foo2()': i64
276..277 'y': &impl Trait<u64>
276..284 'y.foo2()': i64
290..291 'z': impl Trait<u64>
290..298 'z.foo2()': i64
"#]], "#]],
); );
} }
@ -1082,6 +1087,7 @@ fn simple_return_pos_impl_trait() {
cov_mark::check!(lower_rpit); cov_mark::check!(lower_rpit);
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T> { trait Trait<T> {
fn foo(&self) -> T; fn foo(&self) -> T;
} }
@ -1092,16 +1098,16 @@ fn test() {
a.foo(); a.foo();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 62..66 'self': &Self
71..82 '{ loop {} }': ! 104..115 '{ loop {} }': !
73..80 'loop {}': ! 106..113 'loop {}': !
78..80 '{}': () 111..113 '{}': ()
94..129 '{ ...o(); }': () 127..162 '{ ...o(); }': ()
104..105 'a': impl Trait<u64> 137..138 'a': impl Trait<u64>
108..111 'bar': fn bar() -> impl Trait<u64> 141..144 'bar': fn bar() -> impl Trait<u64>
108..113 'bar()': impl Trait<u64> 141..146 'bar()': impl Trait<u64>
119..120 'a': impl Trait<u64> 152..153 'a': impl Trait<u64>
119..126 'a.foo()': u64 152..159 'a.foo()': u64
"#]], "#]],
); );
} }
@ -1110,6 +1116,7 @@ fn test() {
fn more_return_pos_impl_trait() { fn more_return_pos_impl_trait() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Iterator { trait Iterator {
type Item; type Item;
fn next(&mut self) -> Self::Item; fn next(&mut self) -> Self::Item;
@ -1129,37 +1136,37 @@ fn test() {
d.foo(); d.foo();
}"#, }"#,
expect![[r#" expect![[r#"
49..53 'self': &mut Self 82..86 'self': &mut Self
101..105 'self': &Self 134..138 'self': &Self
184..195 '{ loop {} }': ({unknown}, {unknown}) 217..228 '{ loop {} }': ({unknown}, {unknown})
186..193 'loop {}': ! 219..226 'loop {}': !
191..193 '{}': () 224..226 '{}': ()
206..207 't': T 239..240 't': T
268..279 '{ loop {} }': ({unknown}, {unknown}) 301..312 '{ loop {} }': ({unknown}, {unknown})
270..277 'loop {}': ! 303..310 'loop {}': !
275..277 '{}': () 308..310 '{}': ()
291..413 '{ ...o(); }': () 324..446 '{ ...o(); }': ()
301..307 '(a, b)': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) 334..340 '(a, b)': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
302..303 'a': impl Iterator<Item = impl Trait<u32>> 335..336 'a': impl Iterator<Item = impl Trait<u32>>
305..306 'b': impl Trait<u64> 338..339 'b': impl Trait<u64>
310..313 'bar': fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) 343..346 'bar': fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
310..315 'bar()': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) 343..348 'bar()': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
321..322 'a': impl Iterator<Item = impl Trait<u32>> 354..355 'a': impl Iterator<Item = impl Trait<u32>>
321..329 'a.next()': impl Trait<u32> 354..362 'a.next()': impl Trait<u32>
321..335 'a.next().foo()': u32 354..368 'a.next().foo()': u32
341..342 'b': impl Trait<u64> 374..375 'b': impl Trait<u64>
341..348 'b.foo()': u64 374..381 'b.foo()': u64
358..364 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) 391..397 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
359..360 'c': impl Iterator<Item = impl Trait<u128>> 392..393 'c': impl Iterator<Item = impl Trait<u128>>
362..363 'd': impl Trait<u128> 395..396 'd': impl Trait<u128>
367..370 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) 400..403 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
367..377 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) 400..410 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
371..376 '1u128': u128 404..409 '1u128': u128
383..384 'c': impl Iterator<Item = impl Trait<u128>> 416..417 'c': impl Iterator<Item = impl Trait<u128>>
383..391 'c.next()': impl Trait<u128> 416..424 'c.next()': impl Trait<u128>
383..397 'c.next().foo()': u128 416..430 'c.next().foo()': u128
403..404 'd': impl Trait<u128> 436..437 'd': impl Trait<u128>
403..410 'd.foo()': u128 436..443 'd.foo()': u128
"#]], "#]],
); );
} }
@ -1168,6 +1175,7 @@ fn test() {
fn dyn_trait() { fn dyn_trait() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T> { trait Trait<T> {
fn foo(&self) -> T; fn foo(&self) -> T;
fn foo2(&self) -> i64; fn foo2(&self) -> i64;
@ -1186,29 +1194,29 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
z.foo2(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 62..66 'self': &Self
54..58 'self': &Self 87..91 'self': &Self
97..99 '{}': () 130..132 '{}': ()
109..110 'x': dyn Trait<u64> 142..143 'x': dyn Trait<u64>
128..129 'y': &dyn Trait<u64>
148..265 '{ ...2(); }': ()
154..155 'x': dyn Trait<u64>
161..162 'y': &dyn Trait<u64> 161..162 'y': &dyn Trait<u64>
172..173 'z': dyn Trait<u64> 181..298 '{ ...2(); }': ()
176..179 'bar': fn bar() -> dyn Trait<u64>
176..181 'bar()': dyn Trait<u64>
187..188 'x': dyn Trait<u64> 187..188 'x': dyn Trait<u64>
187..194 'x.foo()': u64 194..195 'y': &dyn Trait<u64>
200..201 'y': &dyn Trait<u64> 205..206 'z': dyn Trait<u64>
200..207 'y.foo()': u64 209..212 'bar': fn bar() -> dyn Trait<u64>
213..214 'z': dyn Trait<u64> 209..214 'bar()': dyn Trait<u64>
213..220 'z.foo()': u64 220..221 'x': dyn Trait<u64>
226..227 'x': dyn Trait<u64> 220..227 'x.foo()': u64
226..234 'x.foo2()': i64 233..234 'y': &dyn Trait<u64>
240..241 'y': &dyn Trait<u64> 233..240 'y.foo()': u64
240..248 'y.foo2()': i64 246..247 'z': dyn Trait<u64>
254..255 'z': dyn Trait<u64> 246..253 'z.foo()': u64
254..262 'z.foo2()': i64 259..260 'x': dyn Trait<u64>
259..267 'x.foo2()': i64
273..274 'y': &dyn Trait<u64>
273..281 'y.foo2()': i64
287..288 'z': dyn Trait<u64>
287..295 'z.foo2()': i64
"#]], "#]],
); );
} }
@ -1217,6 +1225,7 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
fn dyn_trait_in_impl() { fn dyn_trait_in_impl() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T, U> { trait Trait<T, U> {
fn foo(&self) -> (T, U); fn foo(&self) -> (T, U);
} }
@ -1233,17 +1242,17 @@ fn test(s: S<u32, i32>) {
s.bar().baz(); s.bar().baz();
}"#, }"#,
expect![[r#" expect![[r#"
32..36 'self': &Self 65..69 'self': &Self
102..106 'self': &S<T, U> 135..139 'self': &S<T, U>
128..139 '{ loop {} }': &dyn Trait<T, U> 161..172 '{ loop {} }': &dyn Trait<T, U>
130..137 'loop {}': ! 163..170 'loop {}': !
135..137 '{}': () 168..170 '{}': ()
175..179 'self': &Self 208..212 'self': &Self
251..252 's': S<u32, i32> 284..285 's': S<u32, i32>
267..289 '{ ...z(); }': () 300..322 '{ ...z(); }': ()
273..274 's': S<u32, i32> 306..307 's': S<u32, i32>
273..280 's.bar()': &dyn Trait<u32, i32> 306..313 's.bar()': &dyn Trait<u32, i32>
273..286 's.bar().baz()': (u32, i32) 306..319 's.bar().baz()': (u32, i32)
"#]], "#]],
); );
} }
@ -1252,6 +1261,7 @@ fn test(s: S<u32, i32>) {
fn dyn_trait_bare() { fn dyn_trait_bare() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait { trait Trait {
fn foo(&self) -> u64; fn foo(&self) -> u64;
} }
@ -1266,22 +1276,22 @@ fn test(x: Trait, y: &Trait) -> u64 {
z.foo(); z.foo();
}"#, }"#,
expect![[r#" expect![[r#"
26..30 'self': &Self 59..63 'self': &Self
60..62 '{}': () 93..95 '{}': ()
72..73 'x': dyn Trait 105..106 'x': dyn Trait
82..83 'y': &dyn Trait 115..116 'y': &dyn Trait
100..175 '{ ...o(); }': () 133..208 '{ ...o(); }': ()
106..107 'x': dyn Trait
113..114 'y': &dyn Trait
124..125 'z': dyn Trait
128..131 'bar': fn bar() -> dyn Trait
128..133 'bar()': dyn Trait
139..140 'x': dyn Trait 139..140 'x': dyn Trait
139..146 'x.foo()': u64 146..147 'y': &dyn Trait
152..153 'y': &dyn Trait 157..158 'z': dyn Trait
152..159 'y.foo()': u64 161..164 'bar': fn bar() -> dyn Trait
165..166 'z': dyn Trait 161..166 'bar()': dyn Trait
165..172 'z.foo()': u64 172..173 'x': dyn Trait
172..179 'x.foo()': u64
185..186 'y': &dyn Trait
185..192 'y.foo()': u64
198..199 'z': dyn Trait
198..205 'z.foo()': u64
"#]], "#]],
); );
} }
@ -1290,6 +1300,7 @@ fn test(x: Trait, y: &Trait) -> u64 {
fn weird_bounds() { fn weird_bounds() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait {} trait Trait {}
fn test( fn test(
a: impl Trait + 'lifetime, a: impl Trait + 'lifetime,
@ -1301,13 +1312,13 @@ fn test(
) {} ) {}
"#, "#,
expect![[r#" expect![[r#"
28..29 'a': impl Trait 61..62 'a': impl Trait
59..60 'b': impl 92..93 'b': impl Sized
82..83 'c': impl Trait 115..116 'c': impl Trait
103..104 'd': impl 136..137 'd': impl Sized
128..129 'e': impl 161..162 'e': impl ?Sized
148..149 'f': impl Trait 181..182 'f': impl Trait + ?Sized
173..175 '{}': () 206..208 '{}': ()
"#]], "#]],
); );
} }
@ -1331,6 +1342,7 @@ fn test(x: (impl Trait + UnknownTrait)) {
fn assoc_type_bindings() { fn assoc_type_bindings() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait { trait Trait {
type Type; type Type;
} }
@ -1352,41 +1364,41 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
get2(S::<str>); get2(S::<str>);
}"#, }"#,
expect![[r#" expect![[r#"
49..50 't': T 82..83 't': T
77..79 '{}': () 110..112 '{}': ()
111..112 't': T 144..145 't': T
122..124 '{}': () 155..157 '{}': ()
154..155 't': T 187..188 't': T
165..168 '{t}': T 198..201 '{t}': T
166..167 't': T 199..200 't': T
256..257 'x': T 289..290 'x': T
262..263 'y': impl Trait<Type = i64> 295..296 'y': impl Trait<Type = i64>
289..397 '{ ...r>); }': () 322..430 '{ ...r>); }': ()
295..298 'get': fn get<T>(T) -> <T as Trait>::Type 328..331 'get': fn get<T>(T) -> <T as Trait>::Type
295..301 'get(x)': u32 328..334 'get(x)': u32
299..300 'x': T 332..333 'x': T
307..311 'get2': fn get2<u32, T>(T) -> u32 340..344 'get2': fn get2<u32, T>(T) -> u32
307..314 'get2(x)': u32 340..347 'get2(x)': u32
312..313 'x': T 345..346 'x': T
320..323 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type 353..356 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type
320..326 'get(y)': i64 353..359 'get(y)': i64
324..325 'y': impl Trait<Type = i64> 357..358 'y': impl Trait<Type = i64>
332..336 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64 365..369 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64
332..339 'get2(y)': i64 365..372 'get2(y)': i64
337..338 'y': impl Trait<Type = i64> 370..371 'y': impl Trait<Type = i64>
345..348 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type 378..381 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type
345..356 'get(set(S))': u64 378..389 'get(set(S))': u64
349..352 'set': fn set<S<u64>>(S<u64>) -> S<u64> 382..385 'set': fn set<S<u64>>(S<u64>) -> S<u64>
349..355 'set(S)': S<u64> 382..388 'set(S)': S<u64>
353..354 'S': S<u64> 386..387 'S': S<u64>
362..366 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 395..399 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
362..374 'get2(set(S))': u64 395..407 'get2(set(S))': u64
367..370 'set': fn set<S<u64>>(S<u64>) -> S<u64> 400..403 'set': fn set<S<u64>>(S<u64>) -> S<u64>
367..373 'set(S)': S<u64> 400..406 'set(S)': S<u64>
371..372 'S': S<u64> 404..405 'S': S<u64>
380..384 'get2': fn get2<str, S<str>>(S<str>) -> str 413..417 'get2': fn get2<str, S<str>>(S<str>) -> str
380..394 'get2(S::<str>)': str 413..427 'get2(S::<str>)': str
385..393 'S::<str>': S<str> 418..426 'S::<str>': S<str>
"#]], "#]],
); );
} }
@ -1495,6 +1507,7 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
fn super_trait_impl_trait_method_resolution() { fn super_trait_impl_trait_method_resolution() {
check_infer( check_infer(
r#" r#"
#[lang = "sized"] trait Sized {}
mod foo { mod foo {
trait SuperTrait { trait SuperTrait {
fn foo(&self) -> u32 {} fn foo(&self) -> u32 {}
@ -1506,12 +1519,12 @@ fn test(x: &impl Trait1) {
x.foo(); x.foo();
}"#, }"#,
expect![[r#" expect![[r#"
49..53 'self': &Self 82..86 'self': &Self
62..64 '{}': () 95..97 '{}': ()
115..116 'x': &impl Trait1 148..149 'x': &impl Trait1
132..148 '{ ...o(); }': () 165..181 '{ ...o(); }': ()
138..139 'x': &impl Trait1 171..172 'x': &impl Trait1
138..145 'x.foo()': u32 171..178 'x.foo()': u32
"#]], "#]],
); );
} }
@ -2299,6 +2312,7 @@ impl TokenStream for Rustc {
fn unify_impl_trait() { fn unify_impl_trait() {
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
#[lang = "sized"] trait Sized {}
trait Trait<T> {} trait Trait<T> {}
fn foo(x: impl Trait<u32>) { loop {} } fn foo(x: impl Trait<u32>) { loop {} }
@ -2316,37 +2330,37 @@ fn test() -> impl Trait<i32> {
S(default()) S(default())
}"#, }"#,
expect![[r#" expect![[r#"
26..27 'x': impl Trait<u32> 59..60 'x': impl Trait<u32>
46..57 '{ loop {} }': () 79..90 '{ loop {} }': ()
48..55 'loop {}': ! 81..88 'loop {}': !
53..55 '{}': () 86..88 '{}': ()
68..69 'x': impl Trait<T> 101..102 'x': impl Trait<T>
91..102 '{ loop {} }': T 124..135 '{ loop {} }': T
93..100 'loop {}': ! 126..133 'loop {}': !
98..100 '{}': () 131..133 '{}': ()
171..182 '{ loop {} }': T 204..215 '{ loop {} }': T
173..180 'loop {}': ! 206..213 'loop {}': !
178..180 '{}': () 211..213 '{}': ()
213..309 '{ ...t()) }': S<{unknown}> 246..342 '{ ...t()) }': S<{unknown}>
223..225 's1': S<u32> 256..258 's1': S<u32>
228..229 'S': S<u32>(u32) -> S<u32> 261..262 'S': S<u32>(u32) -> S<u32>
228..240 'S(default())': S<u32> 261..273 'S(default())': S<u32>
230..237 'default': fn default<u32>() -> u32 263..270 'default': fn default<u32>() -> u32
230..239 'default()': u32 263..272 'default()': u32
246..249 'foo': fn foo(S<u32>) 279..282 'foo': fn foo(S<u32>)
246..253 'foo(s1)': () 279..286 'foo(s1)': ()
250..252 's1': S<u32> 283..285 's1': S<u32>
263..264 'x': i32 296..297 'x': i32
272..275 'bar': fn bar<i32>(S<i32>) -> i32 305..308 'bar': fn bar<i32>(S<i32>) -> i32
272..289 'bar(S(...lt()))': i32 305..322 'bar(S(...lt()))': i32
276..277 'S': S<i32>(i32) -> S<i32> 309..310 'S': S<i32>(i32) -> S<i32>
276..288 'S(default())': S<i32> 309..321 'S(default())': S<i32>
278..285 'default': fn default<i32>() -> i32 311..318 'default': fn default<i32>() -> i32
278..287 'default()': i32 311..320 'default()': i32
295..296 'S': S<{unknown}>({unknown}) -> S<{unknown}> 328..329 'S': S<{unknown}>({unknown}) -> S<{unknown}>
295..307 'S(default())': S<{unknown}> 328..340 'S(default())': S<{unknown}>
297..304 'default': fn default<{unknown}>() -> {unknown} 330..337 'default': fn default<{unknown}>() -> {unknown}
297..306 'default()': {unknown} 330..339 'default()': {unknown}
"#]], "#]],
); );
} }