mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
Refactor argument-position impl Trait
This commit is contained in:
parent
5a0dc2d06d
commit
e502194e7e
@ -602,9 +602,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_lifetime, lifetimes);
|
||||
}
|
||||
TyImplTraitUniversal(_, ref bounds) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
}
|
||||
TyTypeof(expression) => {
|
||||
visitor.visit_nested_body(expression)
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ use syntax::attr;
|
||||
use syntax::ast::*;
|
||||
use syntax::errors;
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind};
|
||||
use syntax::std_inject;
|
||||
@ -106,6 +107,13 @@ pub struct LoweringContext<'a> {
|
||||
is_in_loop_condition: bool,
|
||||
is_in_trait_impl: bool,
|
||||
|
||||
// This is a list of in-band type definitions being generated by
|
||||
// Argument-position `impl Trait`.
|
||||
// When traversing a signature such as `fn foo(x: impl Trait)`,
|
||||
// we record `impl Trait` as a new type parameter, then later
|
||||
// add it on to `foo`s generics.
|
||||
in_band_ty_params: Vec<hir::TyParam>,
|
||||
|
||||
// Used to create lifetime definitions from in-band lifetime usages.
|
||||
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
|
||||
// When a named lifetime is encountered in a function or impl header and
|
||||
@ -197,6 +205,7 @@ pub fn lower_crate(sess: &Session,
|
||||
node_id_to_hir_id: IndexVec::new(),
|
||||
is_generator: false,
|
||||
is_in_trait_impl: false,
|
||||
in_band_ty_params: Vec::new(),
|
||||
lifetimes_to_define: Vec::new(),
|
||||
is_collecting_in_band_lifetimes: false,
|
||||
in_scope_lifetimes: Vec::new(),
|
||||
@ -526,20 +535,23 @@ impl<'a> LoweringContext<'a> {
|
||||
// Creates a new hir::LifetimeDef for every new lifetime encountered
|
||||
// while evaluating `f`. Definitions are created with the parent provided.
|
||||
// If no `parent_id` is provided, no definitions will be returned.
|
||||
fn collect_in_band_lifetime_defs<T, F>(
|
||||
fn collect_in_band_defs<T, F>(
|
||||
&mut self,
|
||||
parent_id: Option<DefId>,
|
||||
f: F
|
||||
) -> (Vec<hir::LifetimeDef>, T) where F: FnOnce(&mut LoweringContext) -> T
|
||||
) -> (Vec<hir::TyParam>, Vec<hir::LifetimeDef>, T) where F: FnOnce(&mut LoweringContext) -> T
|
||||
{
|
||||
assert!(!self.is_collecting_in_band_lifetimes);
|
||||
assert!(self.lifetimes_to_define.is_empty());
|
||||
self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes;
|
||||
|
||||
assert!(self.in_band_ty_params.is_empty());
|
||||
|
||||
let res = f(self);
|
||||
|
||||
self.is_collecting_in_band_lifetimes = false;
|
||||
|
||||
let in_band_ty_params = self.in_band_ty_params.split_off(0);
|
||||
let lifetimes_to_define = self.lifetimes_to_define.split_off(0);
|
||||
|
||||
let lifetime_defs = match parent_id {
|
||||
@ -569,7 +581,7 @@ impl<'a> LoweringContext<'a> {
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
(lifetime_defs, res)
|
||||
(in_band_ty_params, lifetime_defs, res)
|
||||
}
|
||||
|
||||
// Evaluates `f` with the lifetimes in `lt_defs` in-scope.
|
||||
@ -613,11 +625,9 @@ impl<'a> LoweringContext<'a> {
|
||||
res
|
||||
}
|
||||
|
||||
// Appends in-band lifetime defs to the existing set of out-of-band lifetime defs.
|
||||
// Evaluates all within the context of the out-of-band defs.
|
||||
// If provided, `impl_item_id` is used to find the parent impls of impl items so
|
||||
// that their generics are not duplicated.
|
||||
fn add_in_band_lifetime_defs<F, T>(
|
||||
// Appends in-band lifetime defs and argument-position `impl Trait` defs
|
||||
// to the existing set of generics.
|
||||
fn add_in_band_defs<F, T>(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
parent_id: Option<DefId>,
|
||||
@ -625,17 +635,23 @@ impl<'a> LoweringContext<'a> {
|
||||
) -> (hir::Generics, T)
|
||||
where F: FnOnce(&mut LoweringContext) -> T
|
||||
{
|
||||
let (in_band_defs, (mut lowered_generics, res)) =
|
||||
let (in_band_ty_defs, in_band_lifetime_defs, (mut lowered_generics, res)) =
|
||||
self.with_in_scope_lifetime_defs(&generics.lifetimes, |this| {
|
||||
this.collect_in_band_lifetime_defs(parent_id, |this| {
|
||||
this.collect_in_band_defs(parent_id, |this| {
|
||||
(this.lower_generics(generics), f(this))
|
||||
})
|
||||
});
|
||||
|
||||
lowered_generics.ty_params =
|
||||
lowered_generics.ty_params
|
||||
.iter().cloned()
|
||||
.chain(in_band_ty_defs.into_iter())
|
||||
.collect();
|
||||
|
||||
lowered_generics.lifetimes =
|
||||
lowered_generics.lifetimes
|
||||
.iter().cloned()
|
||||
.chain(in_band_defs.into_iter())
|
||||
.chain(in_band_lifetime_defs.into_iter())
|
||||
.collect();
|
||||
|
||||
(lowered_generics, res)
|
||||
@ -922,6 +938,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
TyKind::ImplTrait(ref bounds) => {
|
||||
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||
let span = t.span;
|
||||
match itctx {
|
||||
ImplTraitContext::Existential => {
|
||||
let has_feature = self.sess.features.borrow().conservative_impl_trait;
|
||||
@ -944,7 +961,7 @@ impl<'a> LoweringContext<'a> {
|
||||
id: self.next_id().node_id,
|
||||
predicates: Vec::new().into(),
|
||||
},
|
||||
span: t.span,
|
||||
span,
|
||||
},
|
||||
bounds: hir_bounds,
|
||||
}, lifetimes)
|
||||
@ -956,7 +973,35 @@ impl<'a> LoweringContext<'a> {
|
||||
t.span, GateIssue::Language,
|
||||
"`impl Trait` in argument position is experimental");
|
||||
}
|
||||
hir::TyImplTraitUniversal(def_id, self.lower_bounds(bounds, itctx))
|
||||
|
||||
let def_node_id = self.next_id().node_id;
|
||||
|
||||
// Add a definition for the in-band TyParam
|
||||
let def_index = self.resolver.definitions().create_def_with_parent(
|
||||
def_id.index,
|
||||
def_node_id,
|
||||
DefPathData::ImplTrait,
|
||||
DefIndexAddressSpace::High,
|
||||
Mark::root()
|
||||
);
|
||||
|
||||
let hir_bounds = self.lower_bounds(bounds, itctx);
|
||||
self.in_band_ty_params.push(hir::TyParam {
|
||||
// Set the name to `impl Bound1 + Bound2`
|
||||
name: Symbol::intern(&pprust::ty_to_string(t)),
|
||||
id: def_node_id,
|
||||
bounds: hir_bounds,
|
||||
default: None,
|
||||
span,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
});
|
||||
|
||||
hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
|
||||
span,
|
||||
def: Def::TyParam(DefId::local(def_index)),
|
||||
segments: vec![].into(),
|
||||
})))
|
||||
},
|
||||
ImplTraitContext::Disallowed => {
|
||||
span_err!(self.sess, t.span, E0562,
|
||||
@ -1829,7 +1874,7 @@ impl<'a> LoweringContext<'a> {
|
||||
this.expr_block(body, ThinVec::new())
|
||||
});
|
||||
let (generics, fn_decl) =
|
||||
this.add_in_band_lifetime_defs(generics, fn_def_id, |this|
|
||||
this.add_in_band_defs(generics, fn_def_id, |this|
|
||||
this.lower_fn_decl(decl, fn_def_id, true));
|
||||
|
||||
hir::ItemFn(fn_decl,
|
||||
@ -1883,7 +1928,7 @@ impl<'a> LoweringContext<'a> {
|
||||
ref impl_items) => {
|
||||
let def_id = self.resolver.definitions().opt_local_def_id(id);
|
||||
let (generics, (ifce, lowered_ty)) =
|
||||
self.add_in_band_lifetime_defs(ast_generics, def_id, |this| {
|
||||
self.add_in_band_defs(ast_generics, def_id, |this| {
|
||||
let ifce = ifce.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed)
|
||||
});
|
||||
@ -2059,7 +2104,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
TraitItemKind::Method(ref sig, None) => {
|
||||
let names = this.lower_fn_args_to_names(&sig.decl);
|
||||
this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this|
|
||||
this.add_in_band_defs(&i.generics, fn_def_id, |this|
|
||||
hir::TraitItemKind::Method(
|
||||
this.lower_method_sig(sig, fn_def_id, false),
|
||||
hir::TraitMethod::Required(names)))
|
||||
@ -2070,7 +2115,7 @@ impl<'a> LoweringContext<'a> {
|
||||
this.expr_block(body, ThinVec::new())
|
||||
});
|
||||
|
||||
this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this|
|
||||
this.add_in_band_defs(&i.generics, fn_def_id, |this|
|
||||
hir::TraitItemKind::Method(
|
||||
this.lower_method_sig(sig, fn_def_id, false),
|
||||
hir::TraitMethod::Provided(body_id)))
|
||||
@ -2147,7 +2192,7 @@ impl<'a> LoweringContext<'a> {
|
||||
});
|
||||
let impl_trait_return_allow = !this.is_in_trait_impl;
|
||||
|
||||
this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this|
|
||||
this.add_in_band_defs(&i.generics, fn_def_id, |this|
|
||||
hir::ImplItemKind::Method(
|
||||
this.lower_method_sig(sig, fn_def_id, impl_trait_return_allow),
|
||||
body_id))
|
||||
@ -2280,7 +2325,7 @@ impl<'a> LoweringContext<'a> {
|
||||
ForeignItemKind::Fn(ref fdec, ref generics) => {
|
||||
// Disallow impl Trait in foreign items
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
this.add_in_band_lifetime_defs(
|
||||
this.add_in_band_defs(
|
||||
generics,
|
||||
Some(def_id),
|
||||
|this| (
|
||||
|
@ -1506,7 +1506,7 @@ pub enum Ty_ {
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
|
||||
/// An exsitentially quantified (there exists a type satisfying) `impl
|
||||
/// An existentially quantified (there exists a type satisfying) `impl
|
||||
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
|
||||
///
|
||||
/// The `ExistTy` structure emulates an
|
||||
@ -1518,9 +1518,6 @@ pub enum Ty_ {
|
||||
/// because all in-scope type parameters are captured by `impl Trait`,
|
||||
/// so they are resolved directly through the parent `Generics`.
|
||||
TyImplTraitExistential(ExistTy, HirVec<Lifetime>),
|
||||
/// An universally quantified (for all types satisfying) `impl
|
||||
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
|
||||
TyImplTraitUniversal(DefId, TyParamBounds),
|
||||
/// Unused for now
|
||||
TyTypeof(BodyId),
|
||||
/// TyInfer means the type should be inferred instead of it having been
|
||||
|
@ -424,9 +424,6 @@ impl<'a> State<'a> {
|
||||
hir::TyImplTraitExistential(ref existty, ref _lifetimes) => {
|
||||
self.print_bounds("impl", &existty.bounds[..])?;
|
||||
}
|
||||
hir::TyImplTraitUniversal(_, ref bounds) => {
|
||||
self.print_bounds("impl", &bounds[..])?;
|
||||
}
|
||||
hir::TyArray(ref ty, v) => {
|
||||
self.s.word("[")?;
|
||||
self.print_type(&ty)?;
|
||||
|
@ -312,7 +312,6 @@ impl_stable_hash_for!(enum hir::Ty_ {
|
||||
TyPath(qpath),
|
||||
TyTraitObject(trait_refs, lifetime),
|
||||
TyImplTraitExistential(existty, lifetimes),
|
||||
TyImplTraitUniversal(def_id, bounds),
|
||||
TyTypeof(body_id),
|
||||
TyErr,
|
||||
TyInfer
|
||||
|
@ -2146,19 +2146,6 @@ fn insert_late_bound_lifetimes(
|
||||
visit_where_predicate,
|
||||
&generics.where_clause.predicates
|
||||
);
|
||||
// We need to collect argument impl Trait lifetimes as well,
|
||||
// we do so here.
|
||||
walk_list!(
|
||||
&mut appears_in_where_clause,
|
||||
visit_ty,
|
||||
decl.inputs
|
||||
.iter()
|
||||
.filter(|ty| if let hir::TyImplTraitUniversal(..) = ty.node {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
);
|
||||
for lifetime_def in &generics.lifetimes {
|
||||
if !lifetime_def.bounds.is_empty() {
|
||||
// `'a: 'b` means both `'a` and `'b` are referenced
|
||||
|
@ -30,7 +30,6 @@ use util::nodemap::FxHashSet;
|
||||
|
||||
use std::iter;
|
||||
use syntax::{abi, ast};
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -1050,13 +1049,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
let def_id = tcx.hir.local_def_id(ast_ty.id);
|
||||
self.impl_trait_ty_to_ty(def_id, lifetimes)
|
||||
}
|
||||
hir::TyImplTraitUniversal(fn_def_id, _) => {
|
||||
let impl_trait_def_id = tcx.hir.local_def_id(ast_ty.id);
|
||||
let generics = tcx.generics_of(fn_def_id);
|
||||
let index = generics.type_param_to_index[&impl_trait_def_id.index];
|
||||
tcx.mk_param(index,
|
||||
Symbol::intern(&tcx.hir.node_to_pretty_string(ast_ty.id)))
|
||||
}
|
||||
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
|
||||
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
|
||||
|
@ -43,7 +43,6 @@ use rustc_const_math::ConstInt;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use syntax::{abi, ast};
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
@ -880,32 +879,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let mut allow_defaults = false;
|
||||
|
||||
let no_generics = hir::Generics::empty();
|
||||
let (ast_generics, opt_inputs) = match node {
|
||||
NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
let ast_generics = match node {
|
||||
NodeTraitItem(item) => &item.generics,
|
||||
|
||||
NodeImplItem(item) => {
|
||||
match item.node {
|
||||
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
NodeImplItem(item) => &item.generics,
|
||||
|
||||
NodeItem(item) => {
|
||||
match item.node {
|
||||
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
|
||||
ItemImpl(_, _, _, ref generics, ..) => (generics, None),
|
||||
ItemFn(.., ref generics, _) |
|
||||
ItemImpl(_, _, _, ref generics, ..) => generics,
|
||||
|
||||
ItemTy(_, ref generics) |
|
||||
ItemEnum(_, ref generics) |
|
||||
ItemStruct(_, ref generics) |
|
||||
ItemUnion(_, ref generics) => {
|
||||
allow_defaults = true;
|
||||
(generics, None)
|
||||
generics
|
||||
}
|
||||
|
||||
ItemTrait(_, _, ref generics, ..) | ItemTraitAlias(ref generics, ..) => {
|
||||
@ -926,26 +915,26 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
});
|
||||
|
||||
allow_defaults = true;
|
||||
(generics, None)
|
||||
generics
|
||||
}
|
||||
|
||||
_ => (&no_generics, None)
|
||||
_ => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => (&no_generics, None),
|
||||
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
|
||||
ForeignItemType => (&no_generics, None)
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(ref exist_ty, _), .. }) => {
|
||||
(&exist_ty.generics, None)
|
||||
&exist_ty.generics
|
||||
}
|
||||
|
||||
_ => (&no_generics, None)
|
||||
_ => &no_generics,
|
||||
};
|
||||
|
||||
let has_self = opt_self.is_some();
|
||||
@ -1003,23 +992,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
});
|
||||
|
||||
let fn_ins = opt_inputs.map(|tys| &tys[..]);
|
||||
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
|
||||
let other_type_start = type_start + ast_generics.ty_params.len() as u32;
|
||||
let mut types: Vec<_> = opt_self.into_iter()
|
||||
.chain(types)
|
||||
.chain(univ_impl_trait_info.iter().enumerate().map(|(i, info)| {
|
||||
ty::TypeParameterDef {
|
||||
index: other_type_start + i as u32,
|
||||
name: Symbol::intern(&tcx.hir.node_to_pretty_string(info.id)),
|
||||
def_id: info.def_id,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: Some(SyntheticTyParamKind::ImplTrait),
|
||||
}
|
||||
}))
|
||||
.collect();
|
||||
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
|
||||
|
||||
// provide junk type parameter defs - the only place that
|
||||
// cares about anything but the length is instantiation,
|
||||
@ -1419,50 +1392,36 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let no_generics = hir::Generics::empty();
|
||||
let (ast_generics, opt_inputs) = match node {
|
||||
NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeImplItem(item) => {
|
||||
match item.node {
|
||||
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
let ast_generics = match node {
|
||||
NodeTraitItem(item) => &item.generics,
|
||||
NodeImplItem(item) => &item.generics,
|
||||
|
||||
NodeItem(item) => {
|
||||
match item.node {
|
||||
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
|
||||
|
||||
ItemFn(.., ref generics, _) |
|
||||
ItemImpl(_, _, _, ref generics, ..) |
|
||||
ItemTy(_, ref generics) |
|
||||
ItemEnum(_, ref generics) |
|
||||
ItemStruct(_, ref generics) |
|
||||
ItemUnion(_, ref generics) => {
|
||||
(generics, None)
|
||||
}
|
||||
ItemUnion(_, ref generics) => generics,
|
||||
|
||||
ItemTrait(_, _, ref generics, .., ref items) => {
|
||||
is_trait = Some((ty::TraitRef {
|
||||
def_id,
|
||||
substs: Substs::identity_for_item(tcx, def_id)
|
||||
}, items));
|
||||
(generics, None)
|
||||
generics
|
||||
}
|
||||
|
||||
_ => (&no_generics, None)
|
||||
_ => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => (&no_generics, None),
|
||||
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
|
||||
ForeignItemType => (&no_generics, None),
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1491,7 +1450,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
};
|
||||
}
|
||||
|
||||
_ => (&no_generics, None)
|
||||
_ => &no_generics,
|
||||
};
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
@ -1622,19 +1581,6 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}))
|
||||
}
|
||||
|
||||
// Add predicates from impl Trait arguments
|
||||
let fn_ins = opt_inputs.map(|tys| &tys[..]);
|
||||
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
|
||||
for info in univ_impl_trait_info.iter() {
|
||||
let name = keywords::Invalid.name();
|
||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
||||
index += 1;
|
||||
let bounds = compute_bounds(&icx, param_ty, info.bounds,
|
||||
SizedByDefault::Yes,
|
||||
info.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
}
|
||||
|
||||
// Subtle: before we store the predicates into the tcx, we
|
||||
// sort them so that predicates like `T: Foo<Item=U>` come
|
||||
// before uses of `U`. This avoids false ambiguity errors
|
||||
@ -1795,54 +1741,3 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplTraitUniversalInfo<'hir> {
|
||||
id: ast::NodeId,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
bounds: &'hir [hir::TyParamBound],
|
||||
}
|
||||
|
||||
/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal
|
||||
/// arguments
|
||||
fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
opt_inputs: Option<&'tcx [P<hir::Ty>]>)
|
||||
-> Vec<ImplTraitUniversalInfo<'tcx>>
|
||||
{
|
||||
// A visitor for simply collecting Universally quantified impl Trait arguments
|
||||
struct ImplTraitUniversalVisitor<'tcx> {
|
||||
items: Vec<&'tcx hir::Ty>
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||
if let hir::TyImplTraitUniversal(..) = ty.node {
|
||||
self.items.push(ty);
|
||||
}
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() };
|
||||
|
||||
if let Some(inputs) = opt_inputs {
|
||||
for t in inputs.iter() {
|
||||
visitor.visit_ty(t);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node {
|
||||
ImplTraitUniversalInfo {
|
||||
id: ty.id,
|
||||
def_id: tcx.hir.local_def_id(ty.id),
|
||||
span: ty.span,
|
||||
bounds: bounds
|
||||
}
|
||||
} else {
|
||||
span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug")
|
||||
}).collect()
|
||||
}
|
||||
|
@ -2133,7 +2133,6 @@ impl Clean<Type> for hir::Ty {
|
||||
}
|
||||
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
||||
TyImplTraitExistential(ref exist_ty, ref _lts) => ImplTrait(exist_ty.bounds.clean(cx)),
|
||||
TyImplTraitUniversal(_, ref bounds) => ImplTrait(bounds.clean(cx)),
|
||||
TyInfer | TyErr => Infer,
|
||||
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
|
||||
}
|
||||
|
@ -1070,7 +1070,7 @@ impl<'a> State<'a> {
|
||||
self.print_bounds(prefix, &bounds[..])?;
|
||||
}
|
||||
ast::TyKind::ImplTrait(ref bounds) => {
|
||||
self.print_bounds("impl ", &bounds[..])?;
|
||||
self.print_bounds("impl", &bounds[..])?;
|
||||
}
|
||||
ast::TyKind::Array(ref ty, ref v) => {
|
||||
self.s.word("[")?;
|
||||
|
@ -57,9 +57,8 @@ fn pass_through_elision_with_fn_path<T: Fn(&u32) -> &u32>(
|
||||
x: &T
|
||||
) -> impl Into<&impl Fn(&u32) -> &u32> { x }
|
||||
|
||||
// FIXME(cramertj) Currently ICEing, part of issue #46685:
|
||||
// fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x }
|
||||
// Works:
|
||||
fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x }
|
||||
fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> impl Into<&'a impl Debug> { x }
|
||||
fn foo_no_outer_impl(x: &impl Debug) -> &impl Debug { x }
|
||||
fn foo_explicit_arg<T: Debug>(x: &T) -> impl Into<&impl Debug> { x }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user