Addressed more points raised in review.
This commit is contained in:
parent
783b713b5d
commit
a0a61904f4
@ -63,9 +63,7 @@ pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_
|
|||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds,
|
supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds,
|
||||||
};
|
};
|
||||||
pub use self::util::{
|
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||||
expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfoDignosticBuilder,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use self::chalk_fulfill::{
|
pub use self::chalk_fulfill::{
|
||||||
CanonicalGoal as ChalkCanonicalGoal,
|
CanonicalGoal as ChalkCanonicalGoal,
|
||||||
|
@ -132,18 +132,18 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||||||
// Get predicates declared on the trait.
|
// Get predicates declared on the trait.
|
||||||
let predicates = tcx.super_predicates_of(data.def_id());
|
let predicates = tcx.super_predicates_of(data.def_id());
|
||||||
|
|
||||||
let mut predicates: Vec<_> = predicates.predicates
|
let predicates = predicates.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()))
|
.map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
|
||||||
.collect();
|
|
||||||
debug!("super_predicates: data={:?} predicates={:?}",
|
debug!("super_predicates: data={:?} predicates={:?}",
|
||||||
data, predicates);
|
data, predicates.clone());
|
||||||
|
|
||||||
// Only keep those bounds that we haven't already seen.
|
// Only keep those bounds that we haven't already seen.
|
||||||
// This is necessary to prevent infinite recursion in some
|
// This is necessary to prevent infinite recursion in some
|
||||||
// cases. One common case is when people define
|
// cases. One common case is when people define
|
||||||
// `trait Sized: Sized { }` rather than `trait Sized { }`.
|
// `trait Sized: Sized { }` rather than `trait Sized { }`.
|
||||||
predicates.retain(|pred| self.visited.insert(pred));
|
let visited = &mut self.visited;
|
||||||
|
let predicates = predicates.filter(|pred| visited.insert(pred));
|
||||||
|
|
||||||
self.stack.extend(predicates);
|
self.stack.extend(predicates);
|
||||||
}
|
}
|
||||||
@ -298,13 +298,21 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
|
/// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
|
||||||
let mut path = self.path.clone();
|
/// trait aliases.
|
||||||
path.push((trait_ref, span));
|
pub fn label_with_exp_info(&self,
|
||||||
|
diag: &mut DiagnosticBuilder<'_>,
|
||||||
Self {
|
top_label: &str,
|
||||||
path
|
use_desc: &str
|
||||||
|
) {
|
||||||
|
diag.span_label(self.top().1, top_label);
|
||||||
|
if self.path.len() > 1 {
|
||||||
|
for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
|
||||||
|
diag.span_label(*sp, format!("referenced here ({})", use_desc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
diag.span_label(self.bottom().1,
|
||||||
|
format!("trait alias used in trait object type ({})", use_desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
|
pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
|
||||||
@ -318,33 +326,14 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
|
|||||||
pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
|
pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
|
||||||
self.path.first().unwrap()
|
self.path.first().unwrap()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Emits diagnostic information relating to the expansion of a trait via trait aliases
|
fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
|
||||||
/// (see [`TraitAliasExpansionInfo`]).
|
let mut path = self.path.clone();
|
||||||
pub trait TraitAliasExpansionInfoDignosticBuilder {
|
path.push((trait_ref, span));
|
||||||
fn label_with_exp_info<'tcx>(&mut self,
|
|
||||||
info: &TraitAliasExpansionInfo<'tcx>,
|
|
||||||
top_label: &str,
|
|
||||||
use_desc: &str
|
|
||||||
) -> &mut Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> {
|
Self {
|
||||||
fn label_with_exp_info<'tcx>(&mut self,
|
path
|
||||||
info: &TraitAliasExpansionInfo<'tcx>,
|
|
||||||
top_label: &str,
|
|
||||||
use_desc: &str
|
|
||||||
) -> &mut Self {
|
|
||||||
self.span_label(info.top().1, top_label);
|
|
||||||
if info.path.len() > 1 {
|
|
||||||
for (_, sp) in info.path.iter().rev().skip(1).take(info.path.len() - 2) {
|
|
||||||
self.span_label(*sp, format!("referenced here ({})", use_desc));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.span_label(info.bottom().1,
|
|
||||||
format!("trait alias used in trait object type ({})", use_desc));
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,16 +377,15 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
|
|||||||
// Get components of trait alias.
|
// Get components of trait alias.
|
||||||
let predicates = tcx.super_predicates_of(trait_ref.def_id());
|
let predicates = tcx.super_predicates_of(trait_ref.def_id());
|
||||||
|
|
||||||
let items: Vec<_> = predicates.predicates
|
let items = predicates.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.filter_map(|(pred, span)| {
|
.filter_map(|(pred, span)| {
|
||||||
pred.subst_supertrait(tcx, &trait_ref)
|
pred.subst_supertrait(tcx, &trait_ref)
|
||||||
.to_opt_poly_trait_ref()
|
.to_opt_poly_trait_ref()
|
||||||
.map(|trait_ref| item.clone_and_push(trait_ref, *span))
|
.map(|trait_ref| item.clone_and_push(trait_ref, *span))
|
||||||
})
|
});
|
||||||
.collect();
|
debug!("expand_trait_aliases: items={:?}", items.clone());
|
||||||
debug!("expand_trait_aliases: items={:?}", items);
|
|
||||||
|
|
||||||
self.stack.extend(items);
|
self.stack.extend(items);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ use crate::lint;
|
|||||||
use crate::middle::resolve_lifetime as rl;
|
use crate::middle::resolve_lifetime as rl;
|
||||||
use crate::namespace::Namespace;
|
use crate::namespace::Namespace;
|
||||||
use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||||
use rustc::traits::{self, TraitAliasExpansionInfoDignosticBuilder};
|
use rustc::traits;
|
||||||
use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||||
use rustc::ty::{GenericParamDef, GenericParamDefKind};
|
use rustc::ty::{GenericParamDef, GenericParamDefKind};
|
||||||
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
|
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
|
||||||
@ -976,6 +976,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
let mut projection_bounds = Vec::new();
|
let mut projection_bounds = Vec::new();
|
||||||
let mut potential_assoc_types = Vec::new();
|
let mut potential_assoc_types = Vec::new();
|
||||||
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
||||||
|
// FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is
|
||||||
|
// not straightforward due to the borrow checker.
|
||||||
let bound_trait_refs: Vec<_> = trait_bounds
|
let bound_trait_refs: Vec<_> = trait_bounds
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
@ -998,14 +1000,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
if regular_traits.len() > 1 {
|
if regular_traits.len() > 1 {
|
||||||
let first_trait = ®ular_traits[0];
|
let first_trait = ®ular_traits[0];
|
||||||
let additional_trait = ®ular_traits[1];
|
let additional_trait = ®ular_traits[1];
|
||||||
struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225,
|
let mut err = struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225,
|
||||||
"only auto traits can be used as additional traits in a trait object"
|
"only auto traits can be used as additional traits in a trait object"
|
||||||
)
|
);
|
||||||
.label_with_exp_info(additional_trait, "additional non-auto trait",
|
additional_trait.label_with_exp_info(&mut err,
|
||||||
"additional use")
|
"additional non-auto trait", "additional use");
|
||||||
.label_with_exp_info(first_trait, "first non-auto trait",
|
first_trait.label_with_exp_info(&mut err,
|
||||||
"first use")
|
"first non-auto trait", "first use");
|
||||||
.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if regular_traits.is_empty() && auto_traits.is_empty() {
|
if regular_traits.is_empty() && auto_traits.is_empty() {
|
||||||
|
Loading…
Reference in New Issue
Block a user