Show negative implementation of Sized trait

This commit is contained in:
Guillaume Gomez 2021-02-18 20:46:07 +01:00
parent 9b471a3f5f
commit d20e05b78b
2 changed files with 125 additions and 90 deletions

View file

@ -29,27 +29,24 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
AutoTraitFinder { cx }
}
// FIXME(eddyb) figure out a better way to pass information about
// parametrization of `ty` than `param_env_def_id`.
crate fn get_auto_trait_impls(&mut self, ty: Ty<'tcx>, param_env_def_id: DefId) -> Vec<Item> {
fn generate_for_trait(
&mut self,
ty: Ty<'tcx>,
trait_def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
param_env_def_id: DefId,
f: &auto_trait::AutoTraitFinder<'tcx>,
// If this is set, show only negative trait implementations, not positive ones.
discard_positive_impl: bool,
) -> Option<Item> {
let tcx = self.cx.tcx;
let param_env = tcx.param_env(param_env_def_id);
let f = auto_trait::AutoTraitFinder::new(self.cx.tcx);
debug!("get_auto_trait_impls({:?})", ty);
let auto_traits: Vec<_> = self.cx.auto_traits.iter().cloned().collect();
auto_traits
.into_iter()
.filter_map(|trait_def_id| {
let trait_ref =
ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };
let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };
if !self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)) {
debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
return None;
}
let result =
f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| {
let result = f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| {
let region_data = info.region_data;
let names_map = tcx
@ -84,6 +81,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
let new_generics = match result {
AutoTraitResult::PositiveImpl(new_generics) => {
negative_polarity = false;
if discard_positive_impl {
return None;
}
new_generics
}
AutoTraitResult::NegativeImpl => {
@ -101,8 +101,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
// Instead, we generate `impl !Send for Foo<T>`, which better
// expresses the fact that `Foo<T>` never implements `Send`,
// regardless of the choice of `T`.
let params =
(tcx.generics_of(param_env_def_id), ty::GenericPredicates::default())
let params = (tcx.generics_of(param_env_def_id), ty::GenericPredicates::default())
.clean(self.cx)
.params;
@ -129,8 +128,33 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
blanket_impl: None,
}),
})
}
// FIXME(eddyb) figure out a better way to pass information about
// parametrization of `ty` than `param_env_def_id`.
crate fn get_auto_trait_impls(&mut self, ty: Ty<'tcx>, param_env_def_id: DefId) -> Vec<Item> {
let tcx = self.cx.tcx;
let param_env = tcx.param_env(param_env_def_id);
let f = auto_trait::AutoTraitFinder::new(self.cx.tcx);
debug!("get_auto_trait_impls({:?})", ty);
let auto_traits: Vec<_> = self.cx.auto_traits.iter().cloned().collect();
let mut auto_traits: Vec<Item> = auto_traits
.into_iter()
.filter_map(|trait_def_id| {
self.generate_for_trait(ty, trait_def_id, param_env, param_env_def_id, &f, false)
})
.collect()
.collect();
// We are only interested in case the type *doesn't* implement the Sized trait.
if !ty.is_sized(self.cx.tcx.at(rustc_span::DUMMY_SP), param_env) {
// In case `#![no_core]` is used, `sized_trait` returns nothing.
if let Some(item) = self.cx.tcx.lang_items().sized_trait().and_then(|sized_trait_did| {
self.generate_for_trait(ty, sized_trait_did, param_env, param_env_def_id, &f, true)
}) {
auto_traits.push(item);
}
}
auto_traits
}
fn get_lifetime(region: Region<'_>, names_map: &FxHashMap<Symbol, Lifetime>) -> Lifetime {

View file

@ -32,6 +32,7 @@ use std::{
};
use crate::clean;
use crate::clean::inline::build_external_trait;
use crate::clean::{AttributesExt, MAX_DEF_IDX};
use crate::config::{Options as RustdocOptions, RenderOptions};
use crate::config::{OutputFormat, RenderInfo};
@ -530,6 +531,16 @@ crate fn run_global_ctxt(
module_trait_cache: RefCell::new(FxHashMap::default()),
cache: Cache::default(),
};
// Small hack to force the Sized trait to be present.
//
// Note that in case of `#![no_core]`, the trait is not available.
if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
let mut sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
sized_trait.is_auto = true;
ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait);
}
debug!("crate: {:?}", tcx.hir().krate());
let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));