Skip to content

Commit ea104fa

Browse files
authored
Unrolled build for #146442
Rollup merge of #146442 - Qelxiros:trait-suggestion-generics, r=BoxyUwU Display ?Sized, const, and lifetime parameters in trait item suggestions across a crate boundary context: #145929 This fixes the MetaSized issue and adds const generics and early bound lifetimes. Late bound lifetimes are harder because they aren't returned by `generics_of`. I'm going to look into it, but there's no guarantee I'll be successful. Fixes #146404. r? `@BoxyUwu`
2 parents a9d0a6f + 1a15108 commit ea104fa

File tree

4 files changed

+56
-17
lines changed

4 files changed

+56
-17
lines changed

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub mod intrinsic;
7070
mod region;
7171
pub mod wfcheck;
7272

73+
use std::borrow::Cow;
7374
use std::num::NonZero;
7475

7576
pub use check::{check_abi, check_custom_abi};
@@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
8687
use rustc_middle::ty::error::{ExpectedFound, TypeError};
8788
use rustc_middle::ty::print::with_types_for_signature;
8889
use rustc_middle::ty::{
89-
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
90+
self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
9091
};
9192
use rustc_middle::{bug, span_bug};
9293
use rustc_session::parse::feature_err;
@@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
335336
assoc: ty::AssocItem,
336337
) -> (String, String) {
337338
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
339+
let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
338340
let mut projections = vec![];
339341
for (predicate, _) in predicates {
340342
debug!("predicate {:?}", predicate);
@@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
351353
ty::ClauseKind::Projection(projection_pred) => {
352354
projections.push(bound_predicate.rebind(projection_pred));
353355
}
356+
ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
357+
regions.entry(a).or_default().push(b);
358+
}
354359
_ => {}
355360
}
356361
}
357362

358363
let mut where_clauses = vec![];
359364
let generics = tcx.generics_of(assoc.def_id);
360-
let types_str = generics
365+
let params = generics
361366
.own_params
362367
.iter()
363-
.filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
364-
.map(|p| {
365-
// we just checked that it's a type, so the unwrap can't fail
366-
let ty = tcx.mk_param_from_def(p).as_type().unwrap();
367-
if let Some(bounds) = types.get(&ty) {
368+
.filter(|p| !p.kind.is_synthetic())
369+
.map(|p| match tcx.mk_param_from_def(p).kind() {
370+
ty::GenericArgKind::Type(ty) => {
371+
let bounds =
372+
types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
368373
let mut bounds_str = vec![];
369374
for bound in bounds.iter().copied() {
370375
let mut projections_str = vec![];
@@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
377382
projections_str.push(format!("{} = {}", name, p.term));
378383
}
379384
}
380-
let bound_def_path = tcx.def_path_str(bound);
385+
let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
386+
String::from("?Sized")
387+
} else {
388+
tcx.def_path_str(bound)
389+
};
381390
if projections_str.is_empty() {
382391
where_clauses.push(format!("{}: {}", ty, bound_def_path));
383392
} else {
@@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
393402
} else {
394403
format!("{}: {}", ty, bounds_str.join(" + "))
395404
}
396-
} else {
397-
ty.to_string()
405+
}
406+
ty::GenericArgKind::Const(ct) => {
407+
format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
408+
}
409+
ty::GenericArgKind::Lifetime(region) => {
410+
if let Some(v) = regions.get(&region)
411+
&& !v.is_empty()
412+
{
413+
format!(
414+
"{region}: {}",
415+
v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
416+
)
417+
} else {
418+
region.to_string()
419+
}
398420
}
399421
})
400422
.collect::<Vec<_>>();
@@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
409431
}
410432

411433
let generics =
412-
if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
434+
if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
413435

414436
let where_clauses = if where_clauses.is_empty() {
415437
"".to_string()

tests/ui/suggestions/apitit-unimplemented-method.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ extern crate dep;
44
use dep::*;
55

66
struct Local;
7+
78
impl Trait for Local {}
89
//~^ ERROR not all trait items implemented
910
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
10-
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
11+
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
12+
//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
13+
//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
1114

1215
fn main() {}

tests/ui/suggestions/apitit-unimplemented-method.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
error[E0046]: not all trait items implemented, missing: `foo`, `bar`
2-
--> $DIR/apitit-unimplemented-method.rs:7:1
1+
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `quux`
2+
--> $DIR/apitit-unimplemented-method.rs:8:1
33
|
44
LL | impl Trait for Local {}
5-
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
5+
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `quux` in implementation
66
|
77
= help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
8-
= help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
8+
= help: implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
9+
= help: implement the missing item: `fn baz<const N: usize>() { todo!() }`
10+
= help: implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
911

1012
error: aborting due to 1 previous error
1113

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1+
#![feature(sized_hierarchy)]
2+
3+
use std::marker::MetaSized;
4+
5+
pub struct Foo<T> {
6+
inner: T,
7+
}
8+
19
pub trait Trait {
210
fn foo(_: impl Sized);
3-
fn bar<T>(_: impl Sized);
11+
fn bar<T>(_: impl Sized)
12+
where
13+
Foo<T>: MetaSized;
14+
fn baz<'a, const N: usize>();
15+
fn quux<'a: 'b, 'b, T: ?Sized>();
416
}

0 commit comments

Comments
 (0)