handle const generics, ?Sized, early bound lifetimes

This commit is contained in:
Jeremy Smart 2025-09-11 09:13:44 -04:00
parent f4665ab836
commit 1a1510816a
No known key found for this signature in database
GPG key ID: 5AD8086D5DF29A8F
4 changed files with 56 additions and 17 deletions

View file

@ -70,6 +70,7 @@ pub mod intrinsic;
mod region;
pub mod wfcheck;
use std::borrow::Cow;
use std::num::NonZero;
pub use check::{check_abi, check_custom_abi};
@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::print::with_types_for_signature;
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
assoc: ty::AssocItem,
) -> (String, String) {
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
let mut projections = vec![];
for (predicate, _) in predicates {
debug!("predicate {:?}", predicate);
@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
ty::ClauseKind::Projection(projection_pred) => {
projections.push(bound_predicate.rebind(projection_pred));
}
ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
regions.entry(a).or_default().push(b);
}
_ => {}
}
}
let mut where_clauses = vec![];
let generics = tcx.generics_of(assoc.def_id);
let types_str = generics
let params = generics
.own_params
.iter()
.filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
.map(|p| {
// we just checked that it's a type, so the unwrap can't fail
let ty = tcx.mk_param_from_def(p).as_type().unwrap();
if let Some(bounds) = types.get(&ty) {
.filter(|p| !p.kind.is_synthetic())
.map(|p| match tcx.mk_param_from_def(p).kind() {
ty::GenericArgKind::Type(ty) => {
let bounds =
types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
let mut bounds_str = vec![];
for bound in bounds.iter().copied() {
let mut projections_str = vec![];
@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
projections_str.push(format!("{} = {}", name, p.term));
}
}
let bound_def_path = tcx.def_path_str(bound);
let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
String::from("?Sized")
} else {
tcx.def_path_str(bound)
};
if projections_str.is_empty() {
where_clauses.push(format!("{}: {}", ty, bound_def_path));
} else {
@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
} else {
format!("{}: {}", ty, bounds_str.join(" + "))
}
} else {
ty.to_string()
}
ty::GenericArgKind::Const(ct) => {
format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
}
ty::GenericArgKind::Lifetime(region) => {
if let Some(v) = regions.get(&region)
&& !v.is_empty()
{
format!(
"{region}: {}",
v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
)
} else {
region.to_string()
}
}
})
.collect::<Vec<_>>();
@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
}
let generics =
if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
let where_clauses = if where_clauses.is_empty() {
"".to_string()

View file

@ -4,9 +4,12 @@ extern crate dep;
use dep::*;
struct Local;
impl Trait for Local {}
//~^ ERROR not all trait items implemented
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
fn main() {}

View file

@ -1,11 +1,13 @@
error[E0046]: not all trait items implemented, missing: `foo`, `bar`
--> $DIR/apitit-unimplemented-method.rs:7:1
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `quux`
--> $DIR/apitit-unimplemented-method.rs:8:1
|
LL | impl Trait for Local {}
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `quux` in implementation
|
= help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
= help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
= help: implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
= help: implement the missing item: `fn baz<const N: usize>() { todo!() }`
= help: implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
error: aborting due to 1 previous error

View file

@ -1,4 +1,16 @@
#![feature(sized_hierarchy)]
use std::marker::MetaSized;
pub struct Foo<T> {
inner: T,
}
pub trait Trait {
fn foo(_: impl Sized);
fn bar<T>(_: impl Sized);
fn bar<T>(_: impl Sized)
where
Foo<T>: MetaSized;
fn baz<'a, const N: usize>();
fn quux<'a: 'b, 'b, T: ?Sized>();
}