Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement impl Trait in return type position by anonymization. #35091

Merged
merged 9 commits into from
Aug 12, 2016
3 changes: 3 additions & 0 deletions src/librustc/hir/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
TyPolyTraitRef(bounds) => {
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
TyImplTrait(bounds) => {
TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
},
span: fld.new_span(span),
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyPolyTraitRef(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyTypeof(ref expression) => {
visitor.visit_expr(expression)
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,10 @@ impl<'a> LoweringContext<'a> {
hir::TyTypeof(self.lower_expr(expr))
}
PolyTraitRef(ref bounds) => {
let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect();
hir::TyPolyTraitRef(bounds)
hir::TyPolyTraitRef(self.lower_bounds(bounds))
}
ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
}
Mac(_) => panic!("TyMac should have been expanded by now."),
},
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
});
}

fn visit_ty(&mut self, ty: &'ast Ty) {
self.insert(ty.id, NodeTy(ty));

self.with_parent(ty.id, |this| {
intravisit::walk_ty(this, ty);
});
}

fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
b: &'ast Block, s: Span, id: NodeId) {
assert_eq!(self.parent_node, id);
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
if let TyKind::FixedLengthVec(_, ref length) = ty.node {
self.visit_ast_const_integer(length);
}
if let TyKind::ImplTrait(..) = ty.node {
self.create_def(ty.id, DefPathData::ImplTrait);
}
visit::walk_ty(self, ty);
}

Expand Down Expand Up @@ -428,6 +431,9 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
self.visit_hir_const_integer(length);
}
if let hir::TyImplTrait(..) = ty.node {
self.create_def(ty.id, DefPathData::ImplTrait);
}
intravisit::walk_ty(self, ty);
}

Expand Down
6 changes: 6 additions & 0 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ pub enum DefPathData {
Initializer,
/// Pattern binding
Binding(InternedString),
/// An `impl Trait` type node.
ImplTrait
}

impl Definitions {
Expand Down Expand Up @@ -369,6 +371,10 @@ impl DefPathData {
Initializer => {
InternedString::new("{{initializer}}")
}

ImplTrait => {
InternedString::new("{{impl-Trait}}")
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub enum Node<'ast> {
NodeVariant(&'ast Variant),
NodeExpr(&'ast Expr),
NodeStmt(&'ast Stmt),
NodeTy(&'ast Ty),
NodeLocal(&'ast Pat),
NodePat(&'ast Pat),
NodeBlock(&'ast Block),
Expand All @@ -76,6 +77,7 @@ pub enum MapEntry<'ast> {
EntryVariant(NodeId, &'ast Variant),
EntryExpr(NodeId, &'ast Expr),
EntryStmt(NodeId, &'ast Stmt),
EntryTy(NodeId, &'ast Ty),
EntryLocal(NodeId, &'ast Pat),
EntryPat(NodeId, &'ast Pat),
EntryBlock(NodeId, &'ast Block),
Expand Down Expand Up @@ -104,6 +106,7 @@ impl<'ast> MapEntry<'ast> {
NodeVariant(n) => EntryVariant(p, n),
NodeExpr(n) => EntryExpr(p, n),
NodeStmt(n) => EntryStmt(p, n),
NodeTy(n) => EntryTy(p, n),
NodeLocal(n) => EntryLocal(p, n),
NodePat(n) => EntryPat(p, n),
NodeBlock(n) => EntryBlock(p, n),
Expand All @@ -122,6 +125,7 @@ impl<'ast> MapEntry<'ast> {
EntryVariant(id, _) => id,
EntryExpr(id, _) => id,
EntryStmt(id, _) => id,
EntryTy(id, _) => id,
EntryLocal(id, _) => id,
EntryPat(id, _) => id,
EntryBlock(id, _) => id,
Expand All @@ -144,6 +148,7 @@ impl<'ast> MapEntry<'ast> {
EntryVariant(_, n) => NodeVariant(n),
EntryExpr(_, n) => NodeExpr(n),
EntryStmt(_, n) => NodeStmt(n),
EntryTy(_, n) => NodeTy(n),
EntryLocal(_, n) => NodeLocal(n),
EntryPat(_, n) => NodePat(n),
EntryBlock(_, n) => NodeBlock(n),
Expand Down Expand Up @@ -257,6 +262,7 @@ impl<'ast> Map<'ast> {
EntryVariant(p, _) |
EntryExpr(p, _) |
EntryStmt(p, _) |
EntryTy(p, _) |
EntryLocal(p, _) |
EntryPat(p, _) |
EntryBlock(p, _) |
Expand Down Expand Up @@ -297,6 +303,7 @@ impl<'ast> Map<'ast> {
EntryVariant(p, _) |
EntryExpr(p, _) |
EntryStmt(p, _) |
EntryTy(p, _) |
EntryLocal(p, _) |
EntryPat(p, _) |
EntryBlock(p, _) |
Expand Down Expand Up @@ -680,6 +687,7 @@ impl<'ast> Map<'ast> {
Some(NodeVariant(variant)) => variant.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeTy(ty)) => ty.span,
Some(NodeLocal(pat)) => pat.span,
Some(NodePat(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Expand Down Expand Up @@ -971,6 +979,7 @@ impl<'a> NodePrinter for pprust::State<'a> {
NodeVariant(a) => self.print_variant(&a),
NodeExpr(a) => self.print_expr(&a),
NodeStmt(a) => self.print_stmt(&a),
NodeTy(a) => self.print_type(&a),
NodePat(a) => self.print_pat(&a),
NodeBlock(a) => self.print_block(&a),
NodeLifetime(a) => self.print_lifetime(&a),
Expand Down Expand Up @@ -1059,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some(NodeStmt(ref stmt)) => {
format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
}
Some(NodeTy(ref ty)) => {
format!("type {}{}", pprust::ty_to_string(&ty), id_str)
}
Some(NodeLocal(ref pat)) => {
format!("local {}{}", pprust::pat_to_string(&pat), id_str)
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,8 @@ pub enum Ty_ {
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
/// An `impl TraitA+TraitB` type.
TyImplTrait(TyParamBounds),
/// Unused for now
TyTypeof(P<Expr>),
/// TyInfer means the type should be inferred instead of it having been
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,9 @@ impl<'a> State<'a> {
hir::TyPolyTraitRef(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?;
}
hir::TyFixedLengthVec(ref ty, ref v) => {
word(&mut self.s, "[")?;
self.print_type(&ty)?;
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyClosure(..) |
ty::TyTuple(..) |
ty::TyProjection(..) |
ty::TyParam(..) => {
ty::TyParam(..) |
ty::TyAnon(..) => {
t.super_fold_with(self)
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use ty::{self, Ty, TyCtxt};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::{self, PredicateObligations, ProjectionMode};
use traits::{self, PredicateObligations, Reveal};
use rustc_data_structures::unify::{self, UnificationTable};
use std::cell::{Cell, RefCell, Ref, RefMut};
use std::fmt;
Expand Down Expand Up @@ -147,8 +147,8 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {

// Sadly, the behavior of projection varies a bit depending on the
// stage of compilation. The specifics are given in the
// documentation for `ProjectionMode`.
projection_mode: ProjectionMode,
// documentation for `Reveal`.
projection_mode: Reveal,

// When an error occurs, we want to avoid reporting "derived"
// errors that are due to this original failure. Normally, we
Expand Down Expand Up @@ -459,15 +459,15 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
arenas: ty::CtxtArenas<'tcx>,
tables: Option<RefCell<ty::Tables<'tcx>>>,
param_env: Option<ty::ParameterEnvironment<'gcx>>,
projection_mode: ProjectionMode,
projection_mode: Reveal,
normalize: bool
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
pub fn infer_ctxt(self,
tables: Option<ty::Tables<'tcx>>,
param_env: Option<ty::ParameterEnvironment<'gcx>>,
projection_mode: ProjectionMode)
projection_mode: Reveal)
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
InferCtxtBuilder {
global_tcx: self,
Expand All @@ -479,7 +479,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
}
}

pub fn normalizing_infer_ctxt(self, projection_mode: ProjectionMode)
pub fn normalizing_infer_ctxt(self, projection_mode: Reveal)
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
InferCtxtBuilder {
global_tcx: self,
Expand Down Expand Up @@ -509,7 +509,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
projection_cache: RefCell::new(traits::ProjectionCache::new()),
reported_trait_errors: RefCell::new(FnvHashSet()),
normalize: false,
projection_mode: ProjectionMode::AnyFinal,
projection_mode: Reveal::NotSpecializable,
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: self.sess.err_count(),
obligations_in_snapshot: Cell::new(false),
Expand Down Expand Up @@ -641,7 +641,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
return value;
}

self.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| {
self.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
Expand All @@ -659,7 +659,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
return value;
}

self.infer_ctxt(None, Some(env.clone()), ProjectionMode::Any).enter(|infcx| {
self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
Expand Down Expand Up @@ -736,7 +736,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
Ok(self.tcx.erase_regions(&result))
}

pub fn projection_mode(&self) -> ProjectionMode {
pub fn projection_mode(&self) -> Reveal {
self.projection_mode
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use dep_graph::DepNode;
use hir::def::Def;
use hir::def_id::DefId;
use infer::InferCtxt;
use traits::ProjectionMode;
use traits::Reveal;
use ty::{self, Ty, TyCtxt};
use ty::layout::{LayoutError, Pointer, SizeSkeleton};

Expand All @@ -36,7 +36,7 @@ struct ItemVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
fn visit_const(&mut self, item_id: ast::NodeId, expr: &hir::Expr) {
let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| {
self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
let mut visitor = ExprVisitor {
infcx: &infcx
};
Expand Down Expand Up @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
// const, static and N in [T; N].
fn visit_expr(&mut self, expr: &hir::Expr) {
self.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| {
self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
let mut visitor = ExprVisitor {
infcx: &infcx
};
Expand Down Expand Up @@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
span_bug!(s, "intrinsicck: closure outside of function")
}
let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| {
self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
let mut visitor = ExprVisitor {
infcx: &infcx
};
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ use dep_graph::DepNode;
use hir::def::*;
use hir::pat_util;
use ty::{self, TyCtxt, ParameterEnvironment};
use traits::{self, ProjectionMode};
use traits::{self, Reveal};
use ty::subst::Subst;
use lint;
use util::nodemap::NodeMap;
Expand Down Expand Up @@ -1484,7 +1484,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
let t_ret_subst = t_ret.subst(self.ir.tcx, &param_env.free_substs);
let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env),
ProjectionMode::Any).enter(|infcx| {
Reveal::All).enter(|infcx| {
let cause = traits::ObligationCause::dummy();
traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
});
Expand Down
22 changes: 20 additions & 2 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
constrained_by_input.visit_ty(&arg.ty);
}

let mut appears_in_output = AllCollector { regions: FnvHashSet() };
let mut appears_in_output = AllCollector {
regions: FnvHashSet(),
impl_trait: false
};
intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);

debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
Expand All @@ -842,7 +845,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
//
// Subtle point: because we disallow nested bindings, we can just
// ignore binders here and scrape up all names we see.
let mut appears_in_where_clause = AllCollector { regions: FnvHashSet() };
let mut appears_in_where_clause = AllCollector {
regions: FnvHashSet(),
impl_trait: false
};
for ty_param in generics.ty_params.iter() {
walk_list!(&mut appears_in_where_clause,
visit_ty_param_bound,
Expand All @@ -864,12 +870,16 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
// Late bound regions are those that:
// - appear in the inputs
// - do not appear in the where-clauses
// - are not implicitly captured by `impl Trait`
for lifetime in &generics.lifetimes {
let name = lifetime.lifetime.name;

// appears in the where clauses? early-bound.
if appears_in_where_clause.regions.contains(&name) { continue; }

// any `impl Trait` in the return type? early-bound.
if appears_in_output.impl_trait { continue; }

// does not appear in the inputs, but appears in the return
// type? eventually this will be early-bound, but for now we
// just mark it so we can issue warnings.
Expand Down Expand Up @@ -932,12 +942,20 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,

struct AllCollector {
regions: FnvHashSet<ast::Name>,
impl_trait: bool
}

impl<'v> Visitor<'v> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
self.regions.insert(lifetime_ref.name);
}

fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyImplTrait(_) = ty.node {
self.impl_trait = true;
}
intravisit::walk_ty(self, ty);
}
}
}

Expand Down
Loading