rustc: desugar UFCS as much as possible during HIR lowering.

This commit is contained in:
Eduard Burtescu 2016-10-27 05:17:42 +03:00 committed by Eduard-Mihai Burtescu
parent 34d1352f0e
commit 16b5c2cfef
41 changed files with 637 additions and 486 deletions

View file

@ -14,14 +14,14 @@
* Almost certainly this could (and should) be refactored out of existence.
*/
use hir;
use hir::def::Def;
use ty::{Ty, TyCtxt};
use syntax_pos::Span;
use hir as ast;
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) {
pub fn prohibit_type_params(self, segments: &[hir::PathSegment]) {
for segment in segments {
for typ in segment.parameters.types() {
struct_span_err!(self.sess, typ.span, E0109,
@ -53,24 +53,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
pub fn prim_ty_to_ty(self,
segments: &[ast::PathSegment],
nty: ast::PrimTy)
segments: &[hir::PathSegment],
nty: hir::PrimTy)
-> Ty<'tcx> {
self.prohibit_type_params(segments);
match nty {
ast::TyBool => self.types.bool,
ast::TyChar => self.types.char,
ast::TyInt(it) => self.mk_mach_int(it),
ast::TyUint(uit) => self.mk_mach_uint(uit),
ast::TyFloat(ft) => self.mk_mach_float(ft),
ast::TyStr => self.mk_str()
hir::TyBool => self.types.bool,
hir::TyChar => self.types.char,
hir::TyInt(it) => self.mk_mach_int(it),
hir::TyUint(uit) => self.mk_mach_uint(uit),
hir::TyFloat(ft) => self.mk_mach_float(ft),
hir::TyStr => self.mk_str()
}
}
/// If a type in the AST is a primitive type, return the ty::Ty corresponding
/// to it.
pub fn ast_ty_to_prim_ty(self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> {
if let ast::TyPath(None, ref path) = ast_ty.node {
pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option<Ty<'tcx>> {
if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
if let Def::PrimTy(nty) = self.expect_def(ast_ty.id) {
Some(self.prim_ty_to_ty(&path.segments, nty))
} else {

View file

@ -240,6 +240,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprPath(hir::QPath::TypeRelative(..)) => {
self.lookup_and_handle_definition(expr.id);
}
hir::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.id);
}

View file

@ -186,7 +186,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
hir::ExprInlineAsm(..) => {
self.require_unsafe(expr.span, "use of inline assembly");
}
hir::ExprPath(..) => {
hir::ExprPath(hir::QPath::Resolved(..)) => {
if let Def::Static(def_id, mutbl) = self.tcx.expect_def(expr.id) {
if mutbl {
self.require_unsafe(expr.span, "use of mutable static");

View file

@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
self.walk_adjustment(expr);
match expr.node {
hir::ExprPath(..) => { }
hir::ExprPath(_) => { }
hir::ExprType(ref subexpr, _) => {
self.walk_expr(&subexpr)

View file

@ -160,23 +160,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
if let hir::ExprPath(..) = expr.node {
match self.infcx.tcx.expect_def(expr.id) {
Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];
let to = bare_fn_ty.sig.0.output;
self.check_transmute(expr.span, from, to, expr.id);
}
_ => {
span_bug!(expr.span, "transmute wasn't a bare fn?!");
}
let def = match expr.node {
hir::ExprPath(_) => {
self.infcx.tcx.expect_def(expr.id)
}
_ => Def::Err
};
match def {
Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];
let to = bare_fn_ty.sig.0.output;
self.check_transmute(expr.span, from, to, expr.id);
}
_ => {
span_bug!(expr.span, "transmute wasn't a bare fn?!");
}
}
_ => {}
}
_ => {}
}
intravisit::walk_expr(self, expr);

View file

@ -443,7 +443,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
match expr.node {
// live nodes required for uses or definitions of variables:
hir::ExprPath(..) => {
hir::ExprPath(_) => {
let def = ir.tcx.expect_def(expr.id);
debug!("expr {}: path that leads to {:?}", expr.id, def);
if let Def::Local(..) = def {
@ -922,7 +922,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.node {
// Interesting cases with control flow or which gen/kill
hir::ExprPath(..) => {
hir::ExprPath(hir::QPath::Resolved(..)) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
}
@ -1171,7 +1171,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_exprs(inputs, succ)
}
hir::ExprLit(..) => {
hir::ExprLit(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => {
succ
}
@ -1235,7 +1235,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// just ignore such cases and treat them as reads.
match expr.node {
hir::ExprPath(..) => succ,
hir::ExprPath(_) => succ,
hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
_ => self.propagate_through_expr(expr, succ)
@ -1246,7 +1246,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
-> LiveNode {
match expr.node {
hir::ExprPath(..) => {
hir::ExprPath(hir::QPath::Resolved(..)) => {
self.access_path(expr, succ, acc)
}
@ -1431,8 +1431,8 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
hir::ExprType(..) => {
hir::ExprClosure(..) | hir::ExprPath(_) |
hir::ExprBox(..) | hir::ExprType(..) => {
intravisit::walk_expr(this, expr);
}
}
@ -1482,7 +1482,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn check_lvalue(&mut self, expr: &Expr) {
match expr.node {
hir::ExprPath(..) => {
hir::ExprPath(hir::QPath::Resolved(..)) => {
if let Def::Local(def_id) = self.ir.tcx.expect_def(expr.id) {
// Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually

View file

@ -488,7 +488,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}
hir::ExprPath(..) => {
hir::ExprPath(_) => {
self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id))
}
@ -1157,7 +1157,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}
PatKind::Path(..) | PatKind::Binding(.., None) |
PatKind::Path(_) | PatKind::Binding(.., None) |
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
// always ok
}

View file

@ -91,7 +91,7 @@ struct ReachableContext<'a, 'tcx: 'a> {
impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprPath(..) => {
hir::ExprPath(_) => {
let def = self.tcx.expect_def(expr.id);
let def_id = def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {

View file

@ -244,7 +244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty);
});
}
hir::TyPath(None, ref path) => {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
// if this path references a trait, then this will resolve to
// a trait ref, which introduces a binding scope.
match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
@ -944,13 +944,14 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
impl<'v> Visitor<'v> for ConstrainedCollector {
fn visit_ty(&mut self, ty: &'v hir::Ty) {
match ty.node {
hir::TyPath(Some(_), _) => {
hir::TyPath(hir::QPath::Resolved(Some(_), _)) |
hir::TyPath(hir::QPath::TypeRelative(..)) => {
// ignore lifetimes appearing in associated type
// projections, as they are not *constrained*
// (defined above)
}
hir::TyPath(None, ref path) => {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
// consider only the lifetimes on the final
// segment; I am not sure it's even currently
// valid to have them elsewhere, but even if it

View file

@ -486,6 +486,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
intravisit::walk_pat(self, pat)
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
check_ty(self.tcx, ty,
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
intravisit::walk_ty(self, ty)
}
fn visit_block(&mut self, b: &'tcx hir::Block) {
let old_skip_count = self.in_skip_block;
match b.rules {
@ -553,6 +559,10 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
let method_call = ty::MethodCall::expr(e.id);
tcx.tables().method_map[&method_call].def_id
}
hir::ExprPath(hir::QPath::TypeRelative(..)) => {
span = e.span;
tcx.expect_def(e.id).def_id()
}
hir::ExprField(ref base_e, ref field) => {
span = field.span;
match tcx.tables().expr_ty_adjusted(base_e).sty {
@ -633,6 +643,11 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
debug!("check_pat(pat = {:?})", pat);
if is_internal(tcx, pat.span) { return; }
if let PatKind::Path(hir::QPath::TypeRelative(..)) = pat.node {
let def_id = tcx.expect_def(pat.id).def_id();
maybe_do_stability_check(tcx, def_id, pat.span, cb)
}
let v = match tcx.tables().pat_ty_opt(pat).map(|ty| &ty.sty) {
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(),
_ => return,
@ -656,6 +671,19 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
}
}
pub fn check_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: &hir::Ty,
cb: &mut FnMut(DefId, Span,
&Option<&Stability>,
&Option<DeprecationEntry>)) {
debug!("check_ty(ty = {:?})", ty);
if is_internal(tcx, ty.span) { return; }
if let hir::TyPath(hir::QPath::TypeRelative(..)) = ty.node {
let def_id = tcx.expect_def(ty.id).def_id();
maybe_do_stability_check(tcx, def_id, ty.span, cb);
}
}
fn maybe_do_stability_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: DefId, span: Span,
cb: &mut FnMut(DefId, Span,