Skip to content

Commit

Permalink
Auto merge of rust-lang#46754 - cramertj:refactor-arg-impl, r=nikomat…
Browse files Browse the repository at this point in the history
…sakis

Refactor argument-position impl Trait

Fixes rust-lang#46685, rust-lang#46470

r? @nikomatsakis
cc @chrisvittal
  • Loading branch information
bors committed Dec 21, 2017
2 parents 957dc8d + e502194 commit ab7abfc
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 185 deletions.
3 changes: 0 additions & 3 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
83 changes: 64 additions & 19 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -613,29 +625,33 @@ 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>,
f: F
) -> (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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
});
Expand Down Expand Up @@ -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)))
Expand All @@ -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)))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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| (
Expand Down
5 changes: 1 addition & 4 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,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
Expand All @@ -1523,9 +1523,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
Expand Down
3 changes: 0 additions & 3 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,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)?;
Expand Down
1 change: 0 additions & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 0 additions & 13 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2212,19 +2212,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
Expand Down
8 changes: 0 additions & 8 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -1066,13 +1065,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| {
Expand Down
Loading

0 comments on commit ab7abfc

Please sign in to comment.