rustc: desugar UFCS as much as possible during HIR lowering.
This commit is contained in:
parent
34d1352f0e
commit
16b5c2cfef
41 changed files with 637 additions and 486 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue