Skip to content

Commit b3b23aa

Browse files
Don't document impossible to call default trait items on impls
1 parent d77da9d commit b3b23aa

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

compiler/rustc_middle/src/query/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1951,6 +1951,14 @@ rustc_queries! {
19511951
}
19521952
}
19531953

1954+
query is_impossible_method(key: (DefId, DefId)) -> bool {
1955+
desc { |tcx|
1956+
"checking if {} is impossible to call within {}",
1957+
tcx.def_path_str(key.1),
1958+
tcx.def_path_str(key.0),
1959+
}
1960+
}
1961+
19541962
query method_autoderef_steps(
19551963
goal: CanonicalTyGoal<'tcx>
19561964
) -> MethodAutoderefStepsResult<'tcx> {

compiler/rustc_trait_selection/src/traits/mod.rs

+77-1
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ use rustc_errors::ErrorGuaranteed;
3030
use rustc_hir as hir;
3131
use rustc_hir::def_id::DefId;
3232
use rustc_hir::lang_items::LangItem;
33+
use rustc_infer::traits::TraitEngineExt as _;
3334
use rustc_middle::ty::fold::TypeFoldable;
3435
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
3536
use rustc_middle::ty::visit::TypeVisitable;
36-
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
37+
use rustc_middle::ty::{
38+
self, DefIdTree, GenericParamDefKind, Subst, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
39+
VtblEntry,
40+
};
3741
use rustc_span::{sym, Span};
3842
use smallvec::SmallVec;
3943

@@ -474,6 +478,77 @@ fn subst_and_check_impossible_predicates<'tcx>(
474478
result
475479
}
476480

481+
/// Checks whether a trait's method is impossible to call on a given impl.
482+
///
483+
/// This only considers predicates that reference the impl's generics, and not
484+
/// those that reference the method's generics.
485+
fn is_impossible_method<'tcx>(
486+
tcx: TyCtxt<'tcx>,
487+
(impl_def_id, trait_item_def_id): (DefId, DefId),
488+
) -> bool {
489+
struct ReferencesOnlyParentGenerics<'tcx> {
490+
tcx: TyCtxt<'tcx>,
491+
generics: &'tcx ty::Generics,
492+
trait_item_def_id: DefId,
493+
}
494+
impl<'tcx> ty::TypeVisitor<'tcx> for ReferencesOnlyParentGenerics<'tcx> {
495+
type BreakTy = ();
496+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
497+
// If this is a parameter from the trait item's own generics, then bail
498+
if let ty::Param(param) = t.kind()
499+
&& let param_def_id = self.generics.type_param(param, self.tcx).def_id
500+
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
501+
{
502+
return ControlFlow::BREAK;
503+
}
504+
t.super_visit_with(self)
505+
}
506+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
507+
if let ty::ReEarlyBound(param) = r.kind()
508+
&& let param_def_id = self.generics.region_param(&param, self.tcx).def_id
509+
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
510+
{
511+
return ControlFlow::BREAK;
512+
}
513+
r.super_visit_with(self)
514+
}
515+
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
516+
if let ty::ConstKind::Param(param) = ct.kind()
517+
&& let param_def_id = self.generics.const_param(&param, self.tcx).def_id
518+
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
519+
{
520+
return ControlFlow::BREAK;
521+
}
522+
ct.super_visit_with(self)
523+
}
524+
}
525+
526+
let generics = tcx.generics_of(trait_item_def_id);
527+
let predicates = tcx.predicates_of(trait_item_def_id);
528+
let impl_trait_ref =
529+
tcx.impl_trait_ref(impl_def_id).expect("expected impl to correspond to trait");
530+
let param_env = tcx.param_env(impl_def_id);
531+
532+
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
533+
let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
534+
if pred.visit_with(&mut visitor).is_continue() {
535+
Some(Obligation::new(
536+
ObligationCause::dummy_with_span(*span),
537+
param_env,
538+
ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
539+
))
540+
} else {
541+
None
542+
}
543+
});
544+
545+
tcx.infer_ctxt().ignoring_regions().enter(|ref infcx| {
546+
let mut fulfill_ctxt = <dyn TraitEngine<'_>>::new(tcx);
547+
fulfill_ctxt.register_predicate_obligations(infcx, predicates_for_trait);
548+
!fulfill_ctxt.select_all_or_error(infcx).is_empty()
549+
})
550+
}
551+
477552
#[derive(Clone, Debug)]
478553
enum VtblSegment<'tcx> {
479554
MetadataDSA,
@@ -854,6 +929,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
854929
vtable_entries,
855930
vtable_trait_upcasting_coercion_new_vptr_slot,
856931
subst_and_check_impossible_predicates,
932+
is_impossible_method,
857933
try_unify_abstract_consts: |tcx, param_env_and| {
858934
let (param_env, (a, b)) = param_env_and.into_parts();
859935
const_evaluatable::try_unify_abstract_consts(tcx, (a, b), param_env)

src/librustdoc/html/render/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,15 @@ fn render_impl(
15501550
rendering_params: ImplRenderingParameters,
15511551
) {
15521552
for trait_item in &t.items {
1553+
// Skip over any default trait items that are impossible to call
1554+
// (e.g. if it has a `Self: Sized` bound on an unsized type).
1555+
if let Some(impl_def_id) = parent.item_id.as_def_id()
1556+
&& let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
1557+
&& cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id))
1558+
{
1559+
continue;
1560+
}
1561+
15531562
let n = trait_item.name;
15541563
if i.items.iter().any(|m| m.name == n) {
15551564
continue;
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![crate_name = "foo"]
2+
3+
// Check that default trait items that are impossible to satisfy
4+
5+
pub trait Foo {
6+
fn needs_sized(&self)
7+
where
8+
Self: Sized,
9+
{}
10+
11+
fn no_needs_sized(&self) {}
12+
}
13+
14+
// @!has foo/struct.Bar.html '//*[@id="method.needs_sized"]//h4[@class="code-header"]' \
15+
// "fn needs_sized"
16+
// @has foo/struct.Bar.html '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' \
17+
// "fn no_needs_sized"
18+
pub struct Bar([u8]);
19+
20+
impl Foo for Bar {}

0 commit comments

Comments
 (0)