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

@ -100,7 +100,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
match pat.node {
PatKind::Binding(.., None) |
PatKind::Path(..) |
PatKind::Path(_) |
PatKind::Lit(..) |
PatKind::Range(..) |
PatKind::Wild => {
@ -361,7 +361,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprClosure(..) |
hir::ExprLit(..) |
hir::ExprPath(..) => {
hir::ExprPath(_) => {
self.straightline(expr, pred, None::<hir::Expr>.iter())
}
}

View file

@ -244,6 +244,9 @@ pub trait Visitor<'v> : Sized {
fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
walk_lifetime_def(self, lifetime)
}
fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) {
walk_qpath(self, qpath, id, span)
}
fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
walk_path(self, path)
}
@ -481,11 +484,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
walk_fn_decl(visitor, &function_declaration.decl);
walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
}
TyPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, typ.id);
TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span);
}
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(ty);
@ -508,6 +508,21 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
}
pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: NodeId, span: Span) {
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(qself);
}
visitor.visit_path(path, id)
}
QPath::TypeRelative(ref qself, ref segment) => {
visitor.visit_ty(qself);
visitor.visit_path_segment(span, segment);
}
}
}
pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
for segment in &path.segments {
visitor.visit_path_segment(path.span, segment);
@ -555,18 +570,15 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
visitor.visit_id(pattern.id);
match pattern.node {
PatKind::TupleStruct(ref path, ref children, _) => {
visitor.visit_path(path, pattern.id);
PatKind::TupleStruct(ref qpath, ref children, _) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
walk_list!(visitor, visit_pat, children);
}
PatKind::Path(ref opt_qself, ref path) => {
if let Some(ref qself) = *opt_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, pattern.id)
PatKind::Path(ref qpath) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
}
PatKind::Struct(ref path, ref fields, _) => {
visitor.visit_path(path, pattern.id);
PatKind::Struct(ref qpath, ref fields, _) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
for field in fields {
visitor.visit_name(field.span, field.node.name);
visitor.visit_pat(&field.node.pat)
@ -840,8 +852,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(element);
visitor.visit_expr(count)
}
ExprStruct(ref path, ref fields, ref optional_base) => {
visitor.visit_path(path, expression.id);
ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span);
for field in fields {
visitor.visit_name(field.name.span, field.name.node);
visitor.visit_expr(&field.expr)
@ -917,11 +929,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(main_expression);
visitor.visit_expr(index_expression)
}
ExprPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, expression.id)
ExprPath(ref qpath) => {
visitor.visit_qpath(qpath, expression.id, expression.span);
}
ExprBreak(ref opt_sp_name, ref opt_expr) => {
walk_opt_sp_name(visitor, opt_sp_name);

View file

@ -188,13 +188,13 @@ impl<'a> LoweringContext<'a> {
node: match view_path.node {
ViewPathSimple(ident, ref path) => {
hir::ViewPathSimple(ident.name,
self.lower_path(path, None, ParamMode::Explicit))
self.lower_path(path, ParamMode::Explicit))
}
ViewPathGlob(ref path) => {
hir::ViewPathGlob(self.lower_path(path, None, ParamMode::Explicit))
hir::ViewPathGlob(self.lower_path(path, ParamMode::Explicit))
}
ViewPathList(ref path, ref path_list_idents) => {
hir::ViewPathList(self.lower_path(path, None, ParamMode::Explicit),
hir::ViewPathList(self.lower_path(path, ParamMode::Explicit),
path_list_idents.iter()
.map(|item| self.lower_path_list_item(item))
.collect())
@ -259,14 +259,7 @@ impl<'a> LoweringContext<'a> {
return self.lower_ty(ty);
}
TyKind::Path(ref qself, ref path) => {
let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
hir::QSelf {
ty: self.lower_ty(ty),
position: position,
}
});
let path = self.lower_path(path, qself.as_ref(), ParamMode::Explicit);
hir::TyPath(qself, path)
hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
}
TyKind::ObjectSum(ref ty, ref bounds) => {
hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
@ -308,17 +301,24 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_path(&mut self,
p: &Path,
qself: Option<&hir::QSelf>,
param_mode: ParamMode)
-> hir::Path {
hir::Path {
fn lower_qpath(&mut self,
id: NodeId,
qself: &Option<QSelf>,
p: &Path,
param_mode: ParamMode)
-> hir::QPath {
let qself_position = qself.as_ref().map(|q| q.position);
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
let resolution = self.resolver.get_resolution(id)
.unwrap_or(PathResolution::new(Def::Err));
let proj_start = p.segments.len() - resolution.depth;
let path = P(hir::Path {
global: p.global,
segments: p.segments.iter().enumerate().map(|(i, segment)| {
let PathSegment { identifier, ref parameters } = *segment;
let param_mode = match (qself, param_mode) {
(Some(qself), ParamMode::Optional) if i < qself.position => {
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
let param_mode = match (qself_position, param_mode) {
(Some(j), ParamMode::Optional) if i < j => {
// This segment is part of the trait path in a
// qualified path - one of `a`, `b` or `Trait`
// in `<X as a::b::Trait>::T::U::method`.
@ -326,26 +326,91 @@ impl<'a> LoweringContext<'a> {
}
_ => param_mode
};
hir::PathSegment {
name: identifier.name,
parameters: self.lower_path_parameters(parameters, param_mode),
}
self.lower_path_segment(segment, param_mode)
}).collect(),
span: p.span,
});
// Simple case, either no projections, or only fully-qualified.
// E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
if resolution.depth == 0 {
return hir::QPath::Resolved(qself, path);
}
// Create the innermost type that we're projecting from.
let mut ty = if path.segments.is_empty() {
// If the base path is empty that means there exists a
// syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
qself.expect("missing QSelf for <T>::...")
} else {
// Otherwise, the base path is an implicit `Self` type path,
// e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
// `<I as Iterator>::Item::default`.
let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)));
// Associate that innermost path type with the base Def.
self.resolver.record_resolution(ty.id, resolution.base_def);
ty
};
// Anything after the base path are associated "extensions",
// out of which all but the last one are associated types,
// e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
// * base path is `std::vec::Vec<T>`
// * "extensions" are `IntoIter`, `Item` and `clone`
// * type nodes are:
// 1. `std::vec::Vec<T>` (created above)
// 2. `<std::vec::Vec<T>>::IntoIter`
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
let segment = P(self.lower_path_segment(segment, param_mode));
let qpath = hir::QPath::TypeRelative(ty, segment);
// It's finished, return the extension of the right node type.
if i == p.segments.len() - 1 {
return qpath;
}
// Wrap the associated extension in another type node.
ty = self.ty(p.span, hir::TyPath(qpath));
}
// Should've returned in the for loop above.
span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
proj_start, p.segments.len())
}
fn lower_path(&mut self,
p: &Path,
param_mode: ParamMode)
-> hir::Path {
hir::Path {
global: p.global,
segments: p.segments.iter().map(|segment| {
self.lower_path_segment(segment, param_mode)
}).collect(),
span: p.span,
}
}
fn lower_path_parameters(&mut self,
path_parameters: &PathParameters,
param_mode: ParamMode)
-> hir::PathParameters {
match *path_parameters {
fn lower_path_segment(&mut self,
segment: &PathSegment,
param_mode: ParamMode)
-> hir::PathSegment {
let parameters = match segment.parameters {
PathParameters::AngleBracketed(ref data) => {
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
hir::AngleBracketedParameters(data)
}
PathParameters::Parenthesized(ref data) =>
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
};
hir::PathSegment {
name: segment.identifier.name,
parameters: parameters,
}
}
@ -521,7 +586,7 @@ impl<'a> LoweringContext<'a> {
span}) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
id: id,
path: self.lower_path(path, None, ParamMode::Explicit),
path: self.lower_path(path, ParamMode::Explicit),
ty: self.lower_ty(ty),
span: span,
})
@ -551,7 +616,7 @@ impl<'a> LoweringContext<'a> {
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
hir::TraitRef {
path: self.lower_path(&p.path, None, ParamMode::Explicit),
path: self.lower_path(&p.path, ParamMode::Explicit),
ref_id: p.ref_id,
}
}
@ -908,26 +973,26 @@ impl<'a> LoweringContext<'a> {
respan(pth1.span, pth1.node.name),
sub.as_ref().map(|x| this.lower_pat(x)))
}
_ => hir::PatKind::Path(None, hir::Path::from_name(pth1.span,
pth1.node.name))
_ => {
let path = hir::Path::from_name(pth1.span, pth1.node.name);
hir::PatKind::Path(hir::QPath::Resolved(None, P(path)))
}
}
})
}
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
PatKind::TupleStruct(ref path, ref pats, ddpos) => {
hir::PatKind::TupleStruct(self.lower_path(path, None, ParamMode::Optional),
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
hir::PatKind::TupleStruct(qpath,
pats.iter().map(|x| self.lower_pat(x)).collect(),
ddpos)
}
PatKind::Path(ref qself, ref path) => {
let qself = qself.as_ref().map(|qself| {
hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position }
});
let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
hir::PatKind::Path(qself, path)
hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
}
PatKind::Struct(ref pth, ref fields, etc) => {
let pth = self.lower_path(pth, None, ParamMode::Optional);
PatKind::Struct(ref path, ref fields, etc) => {
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
let fs = fields.iter()
.map(|f| {
Spanned {
@ -940,7 +1005,7 @@ impl<'a> LoweringContext<'a> {
}
})
.collect();
hir::PatKind::Struct(pth, fs, etc)
hir::PatKind::Struct(qpath, fs, etc)
}
PatKind::Tuple(ref elts, ddpos) => {
hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
@ -1266,14 +1331,7 @@ impl<'a> LoweringContext<'a> {
};
}
ExprKind::Path(ref qself, ref path) => {
let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
hir::QSelf {
ty: self.lower_ty(ty),
position: position,
}
});
let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
hir::ExprPath(qself, path)
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
}
ExprKind::Break(opt_ident, ref opt_expr) => {
hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
@ -1306,7 +1364,7 @@ impl<'a> LoweringContext<'a> {
hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
}
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
hir::ExprStruct(P(self.lower_path(path, None, ParamMode::Optional)),
hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
fields.iter().map(|x| self.lower_field(x)).collect(),
maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
}
@ -1688,7 +1746,7 @@ impl<'a> LoweringContext<'a> {
Visibility::Crate(_) => hir::Visibility::Crate,
Visibility::Restricted { ref path, id } => {
hir::Visibility::Restricted {
path: P(self.lower_path(path, None, ParamMode::Explicit)),
path: P(self.lower_path(path, ParamMode::Explicit)),
id: id
}
}
@ -1774,7 +1832,8 @@ impl<'a> LoweringContext<'a> {
}
fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
let expr_path = hir::ExprPath(None, self.path_ident(span, id));
let path = self.path_ident(span, id);
let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(path)));
let expr = self.expr(span, expr_path, ThinVec::new());
let def = {
@ -1792,9 +1851,9 @@ impl<'a> LoweringContext<'a> {
fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, true);
let expr = P(self.expr(path.span, hir::ExprPath(None, path), attrs));
let expr = self.expr(path.span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
self.resolver.record_resolution(expr.id, def);
expr
P(expr)
}
fn expr_match(&mut self,
@ -1821,9 +1880,10 @@ impl<'a> LoweringContext<'a> {
e: Option<P<hir::Expr>>,
attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, false);
let expr = P(self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs));
let qpath = hir::QPath::Resolved(None, P(path));
let expr = self.expr(sp, hir::ExprStruct(qpath, fields, e), attrs);
self.resolver.record_resolution(expr.id, def);
expr
P(expr)
}
fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
@ -1902,10 +1962,11 @@ impl<'a> LoweringContext<'a> {
fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let def = self.resolver.resolve_generated_global_path(&path, true);
let qpath = hir::QPath::Resolved(None, P(path));
let pt = if subpats.is_empty() {
hir::PatKind::Path(None, path)
hir::PatKind::Path(qpath)
} else {
hir::PatKind::TupleStruct(path, subpats, None)
hir::PatKind::TupleStruct(qpath, subpats, None)
};
let pat = self.pat(span, pt);
self.resolver.record_resolution(pat.id, def);
@ -2045,4 +2106,12 @@ impl<'a> LoweringContext<'a> {
});
self.expr_block(block, attrs)
}
fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {
P(hir::Ty {
id: self.next_id(),
node: node,
span: span,
})
}
}

View file

@ -533,7 +533,7 @@ impl Pat {
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Binding(..) |
PatKind::Path(..) => {
PatKind::Path(_) => {
true
}
}
@ -576,16 +576,15 @@ pub enum PatKind {
/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
/// The `bool` is `true` in the presence of a `..`.
Struct(Path, HirVec<Spanned<FieldPat>>, bool),
Struct(QPath, HirVec<Spanned<FieldPat>>, bool),
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// 0 <= position <= subpats.len()
TupleStruct(Path, HirVec<P<Pat>>, Option<usize>),
TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>),
/// A possibly qualified path pattern.
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path(Option<QSelf>, Path),
/// A path pattern for an unit struct/variant or a (maybe-associated) constant.
Path(QPath),
/// A tuple pattern `(a, b)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@ -940,12 +939,8 @@ pub enum Expr_ {
/// An indexing operation (`foo[2]`)
ExprIndex(P<Expr>, P<Expr>),
/// Variable reference, possibly containing `::` and/or type
/// parameters, e.g. foo::bar::<baz>.
///
/// Optionally "qualified",
/// e.g. `<HirVec<T> as SomeTrait>::SomeType`.
ExprPath(Option<QSelf>, Path),
/// Path to a definition, possibly containing lifetime or type parameters.
ExprPath(QPath),
/// A referencing operation (`&a` or `&mut a`)
ExprAddrOf(Mutability, P<Expr>),
@ -963,7 +958,7 @@ pub enum Expr_ {
///
/// For example, `Foo {x: 1, y: 2}`, or
/// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
ExprStruct(P<Path>, HirVec<Field>, Option<P<Expr>>),
ExprStruct(QPath, HirVec<Field>, Option<P<Expr>>),
/// An array literal constructed from one repeated element.
///
@ -972,22 +967,30 @@ pub enum Expr_ {
ExprRepeat(P<Expr>, P<Expr>),
}
/// The explicit Self type in a "qualified path". The actual
/// path, including the trait and the associated item, is stored
/// separately. `position` represents the index of the associated
/// item qualified with this Self type.
///
/// <HirVec<T> as a::b::Trait>::AssociatedItem
/// ^~~~~ ~~~~~~~~~~~~~~^
/// ty position = 3
///
/// <HirVec<T>>::AssociatedItem
/// ^~~~~ ^
/// ty position = 0
/// Optionally `Self`-qualified value/type path or associated extension.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct QSelf {
pub ty: P<Ty>,
pub position: usize,
pub enum QPath {
/// Path to a definition, optionally "fully-qualified" with a `Self`
/// type, if the path points to an associated item in a trait.
///
/// E.g. an unqualified path like `Clone::clone` has `None` for `Self`,
/// while `<Vec<T> as Clone>::clone` has `Some(Vec<T>)` for `Self`,
/// even though they both have the same two-segment `Clone::clone` `Path`.
Resolved(Option<P<Ty>>, P<Path>),
/// Type-related paths, e.g. `<T>::default` or `<T>::Output`.
/// Will be resolved by type-checking to an associated item.
///
/// UFCS source paths can desugar into this, with `Vec::new` turning into
/// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
/// the `X` and `Y` nodes being each a `TyPath(QPath::TypeRelative(..))`.
TypeRelative(P<Ty>, P<PathSegment>)
}
impl fmt::Display for QPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", print::qpath_to_string(self))
}
}
/// Hints at the original code for a `match _ { .. }`
@ -1161,11 +1164,12 @@ pub enum Ty_ {
TyNever,
/// A tuple (`(A, B, C, D,...)`)
TyTup(HirVec<P<Ty>>),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g. `<HirVec<T> as SomeTrait>::SomeType`.
/// A path to a type definition (`module::module::...::Type`), or an
/// associated type, e.g. `<Vec<T> as Trait>::Type` or `<T>::Target`.
///
/// Type parameters are stored in the Path itself
TyPath(Option<QSelf>, Path),
/// Type parameters may be stored in each `PathSegment`.
TyPath(QPath),
/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`

View file

@ -53,9 +53,13 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(Some(..), _) => true,
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Path(hir::QPath::Resolved(Some(..), _)) |
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Path(hir::QPath::Resolved(..)) |
PatKind::Struct(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
@ -69,7 +73,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Path(..) => {
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
PatKind::Path(hir::QPath::Resolved(..)) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
_ => false
@ -171,7 +176,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
pat.walk(|p| {
match p.node {
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Path(hir::QPath::Resolved(..)) |
PatKind::Struct(..) => {
match dm.get(&p.id).map(|d| d.full_def()) {
Some(Def::Variant(id)) |

View file

@ -272,7 +272,11 @@ pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
}
pub fn path_to_string(p: &hir::Path) -> String {
to_string(|s| s.print_path(p, false, 0))
to_string(|s| s.print_path(p, false))
}
pub fn qpath_to_string(p: &hir::QPath) -> String {
to_string(|s| s.print_qpath(p, false))
}
pub fn name_to_string(name: ast::Name) -> String {
@ -528,11 +532,8 @@ impl<'a> State<'a> {
};
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
}
hir::TyPath(None, ref path) => {
self.print_path(path, false, 0)?;
}
hir::TyPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?
hir::TyPath(ref qpath) => {
self.print_qpath(qpath, false)?
}
hir::TyObjectSum(ref ty, ref bounds) => {
self.print_type(&ty)?;
@ -845,7 +846,7 @@ impl<'a> State<'a> {
}
fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
self.print_path(&t.path, false, 0)
self.print_path(&t.path, false)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
@ -1237,11 +1238,11 @@ impl<'a> State<'a> {
}
fn print_expr_struct(&mut self,
path: &hir::Path,
qpath: &hir::QPath,
fields: &[hir::Field],
wth: &Option<P<hir::Expr>>)
-> io::Result<()> {
self.print_path(path, true, 0)?;
self.print_qpath(qpath, true)?;
word(&mut self.s, "{")?;
self.commasep_cmnt(Consistent,
&fields[..],
@ -1345,8 +1346,8 @@ impl<'a> State<'a> {
hir::ExprRepeat(ref element, ref count) => {
self.print_expr_repeat(&element, &count)?;
}
hir::ExprStruct(ref path, ref fields, ref wth) => {
self.print_expr_struct(path, &fields[..], wth)?;
hir::ExprStruct(ref qpath, ref fields, ref wth) => {
self.print_expr_struct(qpath, &fields[..], wth)?;
}
hir::ExprTup(ref exprs) => {
self.print_expr_tup(exprs)?;
@ -1465,11 +1466,8 @@ impl<'a> State<'a> {
self.print_expr(&index)?;
word(&mut self.s, "]")?;
}
hir::ExprPath(None, ref path) => {
self.print_path(path, true, 0)?
}
hir::ExprPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, true)?
hir::ExprPath(ref qpath) => {
self.print_qpath(qpath, true)?
}
hir::ExprBreak(opt_name, ref opt_expr) => {
word(&mut self.s, "break")?;
@ -1622,13 +1620,12 @@ impl<'a> State<'a> {
fn print_path(&mut self,
path: &hir::Path,
colons_before_params: bool,
depth: usize)
colons_before_params: bool)
-> io::Result<()> {
self.maybe_print_comment(path.span.lo)?;
let mut first = !path.global;
for segment in &path.segments[..path.segments.len() - depth] {
for segment in &path.segments {
if first {
first = false
} else {
@ -1644,23 +1641,45 @@ impl<'a> State<'a> {
}
fn print_qpath(&mut self,
path: &hir::Path,
qself: &hir::QSelf,
qpath: &hir::QPath,
colons_before_params: bool)
-> io::Result<()> {
word(&mut self.s, "<")?;
self.print_type(&qself.ty)?;
if qself.position > 0 {
space(&mut self.s)?;
self.word_space("as")?;
let depth = path.segments.len() - qself.position;
self.print_path(&path, false, depth)?;
match *qpath {
hir::QPath::Resolved(None, ref path) => {
self.print_path(path, colons_before_params)
}
hir::QPath::Resolved(Some(ref qself), ref path) => {
word(&mut self.s, "<")?;
self.print_type(qself)?;
space(&mut self.s)?;
self.word_space("as")?;
let mut first = !path.global;
for segment in &path.segments[..path.segments.len() - 1] {
if first {
first = false
} else {
word(&mut self.s, "::")?
}
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
}
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
word(&mut self.s, "<")?;
self.print_type(qself)?;
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
}
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
fn print_path_parameters(&mut self,
@ -1668,7 +1687,15 @@ impl<'a> State<'a> {
colons_before_params: bool)
-> io::Result<()> {
if parameters.is_empty() {
return Ok(());
let infer_types = match *parameters {
hir::AngleBracketedParameters(ref data) => data.infer_types,
hir::ParenthesizedParameters(_) => false
};
// FIXME(eddyb) See the comment below about infer_types.
if !(infer_types && false) {
return Ok(());
}
}
if colons_before_params {
@ -1760,8 +1787,8 @@ impl<'a> State<'a> {
self.print_pat(&p)?;
}
}
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
self.print_path(path, true, 0)?;
PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
self.print_qpath(qpath, true)?;
self.popen()?;
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
@ -1778,14 +1805,11 @@ impl<'a> State<'a> {
}
self.pclose()?;
}
PatKind::Path(None, ref path) => {
self.print_path(path, true, 0)?;
PatKind::Path(ref qpath) => {
self.print_qpath(qpath, true)?;
}
PatKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?;
}
PatKind::Struct(ref path, ref fields, etc) => {
self.print_path(path, true, 0)?;
PatKind::Struct(ref qpath, ref fields, etc) => {
self.print_qpath(qpath, true)?;
self.nbsp()?;
self.word_space("{")?;
self.commasep_cmnt(Consistent,
@ -2118,7 +2142,7 @@ impl<'a> State<'a> {
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
self.print_path(path, false, 0)?;
self.print_path(path, false)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
@ -2132,7 +2156,7 @@ impl<'a> State<'a> {
pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
match vp.node {
hir::ViewPathSimple(name, ref path) => {
self.print_path(path, false, 0)?;
self.print_path(path, false)?;
if path.segments.last().unwrap().name != name {
space(&mut self.s)?;
@ -2144,7 +2168,7 @@ impl<'a> State<'a> {
}
hir::ViewPathGlob(ref path) => {
self.print_path(path, false, 0)?;
self.print_path(path, false)?;
word(&mut self.s, "::*")
}
@ -2152,7 +2176,7 @@ impl<'a> State<'a> {
if path.segments.is_empty() {
word(&mut self.s, "{")?;
} else {
self.print_path(path, false, 0)?;
self.print_path(path, false)?;
word(&mut self.s, "::{")?;
}
self.commasep(Inconsistent, &segments[..], |s, w| s.print_name(w.node.name))?;

View file

@ -1440,7 +1440,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
}
ty_queue.push(&mut_ty.ty);
}
hir::TyPath(ref maybe_qself, ref path) => {
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
match self.tcx.expect_def(cur_ty.id) {
Def::Enum(did) | Def::TyAlias(did) |
Def::Struct(did) | Def::Union(did) => {
@ -1476,15 +1476,12 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
};
let new_path = self.rebuild_path(rebuild_info, lifetime);
let qself = maybe_qself.as_ref().map(|qself| {
hir::QSelf {
ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
anon_nums, region_names),
position: qself.position
}
self.rebuild_arg_ty_or_output(qself, lifetime,
anon_nums, region_names)
});
let to = hir::Ty {
id: cur_ty.id,
node: hir::TyPath(qself, new_path),
node: hir::TyPath(hir::QPath::Resolved(qself, P(new_path))),
span: cur_ty.span
};
new_ty = self.rebuild_ty(new_ty, P(to));

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,

View file

@ -2059,11 +2059,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
match expr.node {
hir::ExprPath(..) => {
// This function can be used during type checking when not all paths are
// fully resolved. Partially resolved paths in expressions can only legally
// refer to associated items which are always rvalues.
match self.expect_resolution(expr.id).base_def {
hir::ExprPath(hir::QPath::Resolved(..)) => {
match self.expect_def(expr.id) {
Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
_ => false,
}
@ -2080,6 +2077,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
true
}
// Partially qualified paths in expressions can only legally
// refer to associated items which are always rvalues.
hir::ExprPath(hir::QPath::TypeRelative(..)) |
hir::ExprCall(..) |
hir::ExprMethodCall(..) |
hir::ExprStruct(..) |