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
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>`
|
||||
|
|
|
|||
|
|
@ -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)) |
|
||||
|
|
|
|||
|
|
@ -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))?;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(..) |
|
||||
|
|
|
|||
|
|
@ -324,6 +324,7 @@ impl Witness {
|
|||
|
||||
ty::TyAdt(adt, _) => {
|
||||
let v = ctor.variant_for_adt(adt);
|
||||
let qpath = hir::QPath::Resolved(None, P(def_to_path(cx.tcx, v.did)));
|
||||
match v.ctor_kind {
|
||||
CtorKind::Fictive => {
|
||||
let field_pats: hir::HirVec<_> = v.fields.iter()
|
||||
|
|
@ -338,16 +339,12 @@ impl Witness {
|
|||
}
|
||||
}).collect();
|
||||
let has_more_fields = field_pats.len() < arity;
|
||||
PatKind::Struct(
|
||||
def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
|
||||
PatKind::Struct(qpath, field_pats, has_more_fields)
|
||||
}
|
||||
CtorKind::Fn => {
|
||||
PatKind::TupleStruct(
|
||||
def_to_path(cx.tcx, v.did), pats.collect(), None)
|
||||
}
|
||||
CtorKind::Const => {
|
||||
PatKind::Path(None, def_to_path(cx.tcx, v.did))
|
||||
PatKind::TupleStruct(qpath, pats.collect(), None)
|
||||
}
|
||||
CtorKind::Const => PatKind::Path(qpath)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -286,9 +286,11 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
|
||||
entry.insert(PathResolution::new(def));
|
||||
}
|
||||
let path = match def {
|
||||
let qpath = match def {
|
||||
Def::StructCtor(def_id, CtorKind::Fn) |
|
||||
Def::VariantCtor(def_id, CtorKind::Fn) => def_to_path(tcx, def_id),
|
||||
Def::VariantCtor(def_id, CtorKind::Fn) => {
|
||||
hir::QPath::Resolved(None, P(def_to_path(tcx, def_id)))
|
||||
}
|
||||
Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
|
||||
id: expr.id,
|
||||
node: PatKind::Lit(P(expr.clone())),
|
||||
|
|
@ -299,10 +301,10 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let pats = args.iter()
|
||||
.map(|expr| const_expr_to_pat(tcx, &*expr, pat_id, span))
|
||||
.collect::<Result<_, _>>()?;
|
||||
PatKind::TupleStruct(path, pats, None)
|
||||
PatKind::TupleStruct(qpath, pats, None)
|
||||
}
|
||||
|
||||
hir::ExprStruct(ref path, ref fields, None) => {
|
||||
hir::ExprStruct(ref qpath, ref fields, None) => {
|
||||
let field_pats =
|
||||
fields.iter()
|
||||
.map(|field| Ok(codemap::Spanned {
|
||||
|
|
@ -314,7 +316,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
},
|
||||
}))
|
||||
.collect::<Result<_, _>>()?;
|
||||
PatKind::Struct((**path).clone(), field_pats, false)
|
||||
PatKind::Struct(qpath.clone(), field_pats, false)
|
||||
}
|
||||
|
||||
hir::ExprArray(ref exprs) => {
|
||||
|
|
@ -324,10 +326,17 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
PatKind::Slice(pats, None, hir::HirVec::new())
|
||||
}
|
||||
|
||||
hir::ExprPath(_, ref path) => {
|
||||
hir::ExprPath(_) => {
|
||||
match tcx.expect_def(expr.id) {
|
||||
Def::StructCtor(_, CtorKind::Const) |
|
||||
Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()),
|
||||
Def::VariantCtor(_, CtorKind::Const) => {
|
||||
match expr.node {
|
||||
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
|
||||
PatKind::Path(hir::QPath::Resolved(None, path.clone()))
|
||||
}
|
||||
_ => bug!()
|
||||
}
|
||||
}
|
||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||
let substs = Some(tcx.tables().node_id_item_substs(expr.id)
|
||||
.unwrap_or_else(|| tcx.intern_substs(&[])));
|
||||
|
|
@ -788,14 +797,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
|
||||
}
|
||||
}
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(_) => {
|
||||
// This function can be used before type checking when not all paths are fully resolved.
|
||||
// FIXME: There's probably a better way to make sure we don't panic here.
|
||||
let resolution = tcx.expect_resolution(e.id);
|
||||
if resolution.depth != 0 {
|
||||
signal!(e, UnresolvedPath);
|
||||
}
|
||||
match resolution.base_def {
|
||||
let def = match tcx.expect_def_or_none(e.id) {
|
||||
Some(def) => def,
|
||||
None => signal!(e, UnresolvedPath)
|
||||
};
|
||||
match def {
|
||||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let substs = if let ExprTypeChecked = ty_hint {
|
||||
|
|
@ -1358,17 +1367,12 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut diag = report_const_eval_err(
|
||||
tcx, &err, count_expr.span, reason);
|
||||
|
||||
match count_expr.node {
|
||||
hir::ExprPath(None, hir::Path {
|
||||
global: false,
|
||||
ref segments,
|
||||
..
|
||||
}) if segments.len() == 1 => {
|
||||
if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
|
||||
if !path.global && path.segments.len() == 1 {
|
||||
if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
|
||||
diag.note(&format!("`{}` is a variable", segments[0].name));
|
||||
diag.note(&format!("`{}` is a variable", path.segments[0].name));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ enum SawAbiComponent<'a> {
|
|||
SawImplItem(SawTraitOrImplItemComponent),
|
||||
SawStructField,
|
||||
SawVariant,
|
||||
SawQPath,
|
||||
SawPath(bool),
|
||||
SawPathSegment,
|
||||
SawPathParameters,
|
||||
|
|
@ -259,7 +260,7 @@ enum SawExprComponent<'a> {
|
|||
SawExprAssign,
|
||||
SawExprAssignOp(hir::BinOp_),
|
||||
SawExprIndex,
|
||||
SawExprPath(Option<usize>),
|
||||
SawExprPath,
|
||||
SawExprAddrOf(hir::Mutability),
|
||||
SawExprRet,
|
||||
SawExprInlineAsm(&'a hir::InlineAsm),
|
||||
|
|
@ -333,7 +334,7 @@ fn saw_expr<'a>(node: &'a Expr_,
|
|||
ExprField(_, name) => (SawExprField(name.node.as_str()), false),
|
||||
ExprTupField(_, id) => (SawExprTupField(id.node), false),
|
||||
ExprIndex(..) => (SawExprIndex, true),
|
||||
ExprPath(ref qself, _) => (SawExprPath(qself.as_ref().map(|q| q.position)), false),
|
||||
ExprPath(_) => (SawExprPath, false),
|
||||
ExprAddrOf(m, _) => (SawExprAddrOf(m), false),
|
||||
ExprBreak(id, _) => (SawExprBreak(id.map(|id| id.node.as_str())), false),
|
||||
ExprAgain(id) => (SawExprAgain(id.map(|id| id.node.as_str())), false),
|
||||
|
|
@ -411,7 +412,7 @@ fn saw_pat(node: &PatKind) -> SawPatComponent {
|
|||
PatKind::Binding(bindingmode, ..) => SawPatBinding(bindingmode),
|
||||
PatKind::Struct(..) => SawPatStruct,
|
||||
PatKind::TupleStruct(..) => SawPatTupleStruct,
|
||||
PatKind::Path(..) => SawPatPath,
|
||||
PatKind::Path(_) => SawPatPath,
|
||||
PatKind::Tuple(..) => SawPatTuple,
|
||||
PatKind::Box(..) => SawPatBox,
|
||||
PatKind::Ref(_, mutability) => SawPatRef(mutability),
|
||||
|
|
@ -447,7 +448,7 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
|
|||
TyBareFn(ref barefnty) => SawTyBareFn(barefnty.unsafety, barefnty.abi),
|
||||
TyNever => SawTyNever,
|
||||
TyTup(..) => SawTyTup,
|
||||
TyPath(..) => SawTyPath,
|
||||
TyPath(_) => SawTyPath,
|
||||
TyObjectSum(..) => SawTyObjectSum,
|
||||
TyPolyTraitRef(..) => SawTyPolyTraitRef,
|
||||
TyImplTrait(..) => SawTyImplTrait,
|
||||
|
|
@ -655,6 +656,13 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
|
|||
visit::walk_struct_field(self, s)
|
||||
}
|
||||
|
||||
fn visit_qpath(&mut self, qpath: &'tcx QPath, id: NodeId, span: Span) {
|
||||
debug!("visit_qpath: st={:?}", self.st);
|
||||
SawQPath.hash(self.st);
|
||||
self.hash_discriminant(qpath);
|
||||
visit::walk_qpath(self, qpath, id, span)
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
|
||||
debug!("visit_path: st={:?}", self.st);
|
||||
SawPath(path.global).hash(self.st);
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ impl LateLintPass for NonUpperCaseGlobals {
|
|||
|
||||
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
|
||||
// Lint for constants that look like binding identifiers (#7526)
|
||||
if let PatKind::Path(None, ref path) = p.node {
|
||||
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
|
||||
if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
|
||||
if let Def::Const(..) = cx.tcx.expect_def(p.id) {
|
||||
NonUpperCaseGlobals::check_upper_case(cx,
|
||||
|
|
|
|||
|
|
@ -718,6 +718,12 @@ impl LateLintPass for Deprecated {
|
|||
&mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) {
|
||||
stability::check_ty(cx.tcx, ty,
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, _: &LateContext, item: &hir::ImplItem) {
|
||||
self.push_item(item.id);
|
||||
}
|
||||
|
|
@ -1204,7 +1210,7 @@ impl LateLintPass for MutableTransmutes {
|
|||
expr: &hir::Expr)
|
||||
-> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
|
||||
match expr.node {
|
||||
hir::ExprPath(..) => (),
|
||||
hir::ExprPath(_) => (),
|
||||
_ => return None,
|
||||
}
|
||||
if let Def::Fn(did) = cx.tcx.expect_def(expr.id) {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl LintPass for PathStatements {
|
|||
impl LateLintPass for PathStatements {
|
||||
fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
|
||||
if let hir::StmtSemi(ref expr, _) = s.node {
|
||||
if let hir::ExprPath(..) = expr.node {
|
||||
if let hir::ExprPath(_) = expr.node {
|
||||
cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
args: vec![fun.to_ref(), tupled_args.to_ref()]
|
||||
}
|
||||
} else {
|
||||
let adt_data = if let hir::ExprPath(..) = fun.node {
|
||||
let adt_data = if let hir::ExprPath(hir::QPath::Resolved(..)) = fun.node {
|
||||
// Tuple-like ADTs are represented as ExprCall. We convert them here.
|
||||
expr_ty.ty_adt_def().and_then(|adt_def|{
|
||||
match cx.tcx.expect_def(fun.id) {
|
||||
|
|
@ -531,7 +531,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(_) => {
|
||||
convert_path_expr(cx, expr)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(_) => {
|
||||
match v.tcx.expect_def(e.id) {
|
||||
Def::VariantCtor(_, CtorKind::Const) => {
|
||||
// Size is determined by the whole enum, may be non-zero.
|
||||
|
|
|
|||
|
|
@ -218,6 +218,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
self.record("LifetimeDef", Id::None, lifetime);
|
||||
hir_visit::walk_lifetime_def(self, lifetime)
|
||||
}
|
||||
fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) {
|
||||
self.record("QPath", Id::None, qpath);
|
||||
hir_visit::walk_qpath(self, qpath, id, span)
|
||||
}
|
||||
fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) {
|
||||
self.record("Path", Id::None, path);
|
||||
hir_visit::walk_path(self, path)
|
||||
|
|
@ -234,7 +238,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
self.record("PathSegment", Id::None, path_segment);
|
||||
hir_visit::walk_path_segment(self, path_span, path_segment)
|
||||
}
|
||||
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) {
|
||||
self.record("TypeBinding", Id::Node(type_binding.id), type_binding);
|
||||
hir_visit::walk_assoc_type_binding(self, type_binding)
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
|
|||
|
||||
fn visit_expr(&mut self, e: &'ast hir::Expr) {
|
||||
match e.node {
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(_) => {
|
||||
match self.def_map.get(&e.id).map(|d| d.base_def) {
|
||||
Some(Def::Static(def_id, _)) |
|
||||
Some(Def::AssociatedConst(def_id)) |
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
|
||||
fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
|
||||
if let hir::TyPath(..) = ty.node {
|
||||
if let hir::TyPath(_) = ty.node {
|
||||
match self.tcx.expect_def(ty.id) {
|
||||
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
|
||||
Some(AccessLevel::Public)
|
||||
|
|
@ -306,11 +306,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
|
||||
// Make the type hidden under a type alias reachable
|
||||
fn reach_aliased_type(&mut self, item: &'tcx hir::Item, path: &'tcx hir::Path) {
|
||||
fn reach_aliased_type(&mut self, item: &'tcx hir::Item, segment: &'tcx hir::PathSegment) {
|
||||
if let hir::ItemTy(ref ty, ref generics) = item.node {
|
||||
// See `fn is_public_type_alias` for details
|
||||
self.visit_ty(ty);
|
||||
let provided_params = path.segments.last().unwrap().parameters.types().len();
|
||||
let provided_params = segment.parameters.types().len();
|
||||
for ty_param in &generics.ty_params[provided_params..] {
|
||||
if let Some(ref default_ty) = ty_param.default {
|
||||
self.visit_ty(default_ty);
|
||||
|
|
@ -328,7 +328,12 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
|
|||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||
if let hir::TyPath(_, ref path) = ty.node {
|
||||
let path_segment = match ty.node {
|
||||
hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
|
||||
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
|
||||
_ => None
|
||||
};
|
||||
if let Some(segment) = path_segment {
|
||||
let def = self.ev.tcx.expect_def(ty.id);
|
||||
match def {
|
||||
Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) |
|
||||
|
|
@ -344,7 +349,7 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
|
|||
// Type aliases are substituted. Associated type aliases are not
|
||||
// substituted yet, but ideally they should be.
|
||||
if self.ev.get(item.id).is_none() {
|
||||
self.reach_aliased_type(item, path);
|
||||
self.reach_aliased_type(item, segment);
|
||||
}
|
||||
} else {
|
||||
self.ev.update(item.id, Some(AccessLevel::Reachable));
|
||||
|
|
@ -461,7 +466,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(hir::QPath::Resolved(..)) => {
|
||||
if let def @ Def::StructCtor(_, CtorKind::Fn) = self.tcx.expect_def(expr.id) {
|
||||
let adt_def = self.tcx.expect_variant_def(def);
|
||||
let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
|
||||
|
|
@ -606,7 +611,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: &hir::Ty) {
|
||||
if let hir::TyPath(..) = ty.node {
|
||||
if let hir::TyPath(_) = ty.node {
|
||||
if self.inner.path_is_private_type(ty.id) {
|
||||
self.contains_private = true;
|
||||
// found what we're looking for so let's stop
|
||||
|
|
@ -844,7 +849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'tcx hir::Ty) {
|
||||
if let hir::TyPath(..) = t.node {
|
||||
if let hir::TyPath(_) = t.node {
|
||||
if self.path_is_private_type(t.id) {
|
||||
self.old_error_set.insert(t.id);
|
||||
}
|
||||
|
|
@ -906,7 +911,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
||||
// Return the visibility of the type alias's least visible component type when substituted
|
||||
fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
|
||||
fn substituted_alias_visibility(&self, item: &hir::Item, segment: &hir::PathSegment)
|
||||
-> Option<ty::Visibility> {
|
||||
// Type alias is considered public if the aliased type is
|
||||
// public, even if the type alias itself is private. So, something
|
||||
|
|
@ -921,7 +926,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
|||
// type Alias<T = Private> = T;
|
||||
// pub fn f() -> Alias {...} // `Private` is implicitly used here, so it must be public
|
||||
// ```
|
||||
let provided_params = path.segments.last().unwrap().parameters.types().len();
|
||||
let provided_params = segment.parameters.types().len();
|
||||
for ty_param in &generics.ty_params[provided_params..] {
|
||||
if let Some(ref default_ty) = ty_param.default {
|
||||
check.visit_ty(default_ty);
|
||||
|
|
@ -936,7 +941,12 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: &hir::Ty) {
|
||||
if let hir::TyPath(_, ref path) = ty.node {
|
||||
let path_segment = match ty.node {
|
||||
hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
|
||||
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
|
||||
_ => None
|
||||
};
|
||||
if let Some(segment) = path_segment {
|
||||
match self.tcx.expect_def(ty.id) {
|
||||
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
|
||||
// Public
|
||||
|
|
@ -961,7 +971,7 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
|
|||
}
|
||||
|
||||
let item = self.tcx.map.expect_item(node_id);
|
||||
let vis = match self.substituted_alias_visibility(item, path) {
|
||||
let vis = match self.substituted_alias_visibility(item, segment) {
|
||||
Some(vis) => vis,
|
||||
None => ty::Visibility::from_hir(&item.vis, node_id, self.tcx),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -952,7 +952,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
|
||||
let tcx = self.tcx();
|
||||
match ty.node {
|
||||
hir::TyPath(None, ref path) => {
|
||||
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
|
||||
let resolution = tcx.expect_resolution(ty.id);
|
||||
match resolution.base_def {
|
||||
Def::Trait(trait_def_id) if resolution.depth == 0 => {
|
||||
|
|
@ -1261,12 +1261,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
// the whole path.
|
||||
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
|
||||
// parameter or Self.
|
||||
fn associated_path_def_to_ty(&self,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
ty_path_def: Def,
|
||||
item_segment: &hir::PathSegment)
|
||||
-> (Ty<'tcx>, Def)
|
||||
pub fn associated_path_def_to_ty(&self,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
ty_path_def: Def,
|
||||
item_segment: &hir::PathSegment)
|
||||
-> (Ty<'tcx>, Def)
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
let assoc_name = item_segment.name;
|
||||
|
|
@ -1412,54 +1412,55 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
}
|
||||
|
||||
// Check the base def in a PathResolution and convert it to a Ty. If there are
|
||||
// associated types in the PathResolution, these will need to be separately
|
||||
// resolved.
|
||||
fn base_def_to_ty(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
def: Def,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
base_path_ref_id: ast::NodeId,
|
||||
base_segments: &[hir::PathSegment],
|
||||
permit_variants: bool)
|
||||
-> Ty<'tcx> {
|
||||
// Check a type Def and convert it to a Ty.
|
||||
pub fn def_to_ty(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
def: Def,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
path_id: ast::NodeId,
|
||||
path_segments: &[hir::PathSegment],
|
||||
permit_variants: bool)
|
||||
-> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})",
|
||||
def, opt_self_ty, base_segments);
|
||||
debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})",
|
||||
def, opt_self_ty, path_segments);
|
||||
|
||||
match def {
|
||||
Def::Trait(trait_def_id) => {
|
||||
// N.B. this case overlaps somewhat with
|
||||
// TyObjectSum, see that fn for details
|
||||
|
||||
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
|
||||
|
||||
self.trait_path_to_object_type(rscope,
|
||||
span,
|
||||
trait_def_id,
|
||||
base_path_ref_id,
|
||||
base_segments.last().unwrap(),
|
||||
path_id,
|
||||
path_segments.last().unwrap(),
|
||||
span,
|
||||
partition_bounds(tcx, span, &[]))
|
||||
}
|
||||
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
|
||||
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(rscope, span, did, base_segments.last().unwrap())
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(rscope, span, did, path_segments.last().unwrap())
|
||||
}
|
||||
Def::Variant(did) if permit_variants => {
|
||||
// Convert "variant type" as if it were a real type.
|
||||
// The resulting `Ty` is type of the variant's enum for now.
|
||||
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(rscope,
|
||||
span,
|
||||
param_mode,
|
||||
tcx.parent_def_id(did).unwrap(),
|
||||
base_segments.last().unwrap())
|
||||
path_segments.last().unwrap())
|
||||
}
|
||||
Def::TyParam(did) => {
|
||||
tcx.prohibit_type_params(base_segments);
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments);
|
||||
|
||||
let node_id = tcx.map.as_local_node_id(did).unwrap();
|
||||
let param = tcx.ty_param_defs.borrow().get(&node_id)
|
||||
|
|
@ -1481,7 +1482,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
Def::SelfTy(_, Some(def_id)) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
|
||||
tcx.prohibit_type_params(base_segments);
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments);
|
||||
let ty = tcx.item_type(def_id);
|
||||
if let Some(free_substs) = self.get_free_substs() {
|
||||
ty.subst(tcx, free_substs)
|
||||
|
|
@ -1491,34 +1493,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
Def::SelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
tcx.prohibit_type_params(base_segments);
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prohibit_type_params(path_segments);
|
||||
tcx.mk_self_type()
|
||||
}
|
||||
Def::AssociatedTy(def_id) => {
|
||||
tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]);
|
||||
tcx.prohibit_type_params(&path_segments[..path_segments.len()-2]);
|
||||
let trait_did = tcx.parent_def_id(def_id).unwrap();
|
||||
self.qpath_to_ty(rscope,
|
||||
span,
|
||||
opt_self_ty,
|
||||
trait_did,
|
||||
&base_segments[base_segments.len()-2],
|
||||
base_segments.last().unwrap())
|
||||
}
|
||||
Def::Mod(..) => {
|
||||
// Used as sentinel by callers to indicate the `<T>::A::B::C` form.
|
||||
// FIXME(#22519) This part of the resolution logic should be
|
||||
// avoided entirely for that form, once we stop needed a Def
|
||||
// for `associated_path_def_to_ty`.
|
||||
// Fixing this will also let use resolve <Self>::Foo the same way we
|
||||
// resolve Self::Foo, at the moment we can't resolve the former because
|
||||
// we don't have the trait information around, which is just sad.
|
||||
|
||||
assert!(base_segments.is_empty());
|
||||
|
||||
opt_self_ty.expect("missing T in <T>::a::b::c")
|
||||
&path_segments[path_segments.len()-2],
|
||||
path_segments.last().unwrap())
|
||||
}
|
||||
Def::PrimTy(prim_ty) => {
|
||||
tcx.prim_ty_to_ty(base_segments, prim_ty)
|
||||
assert_eq!(opt_self_ty, None);
|
||||
tcx.prim_ty_to_ty(path_segments, prim_ty)
|
||||
}
|
||||
Def::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
|
|
@ -1535,50 +1526,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
}
|
||||
|
||||
// Resolve possibly associated type path into a type and final definition.
|
||||
// Note that both base_segments and assoc_segments may be empty, although not at same time.
|
||||
pub fn finish_resolving_def_to_ty(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
base_def: Def,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
base_path_ref_id: ast::NodeId,
|
||||
base_segments: &[hir::PathSegment],
|
||||
assoc_segments: &[hir::PathSegment],
|
||||
permit_variants: bool)
|
||||
-> (Ty<'tcx>, Def) {
|
||||
// Convert the base type.
|
||||
debug!("finish_resolving_def_to_ty(base_def={:?}, \
|
||||
base_segments={:?}, \
|
||||
assoc_segments={:?})",
|
||||
base_def,
|
||||
base_segments,
|
||||
assoc_segments);
|
||||
let base_ty = self.base_def_to_ty(rscope,
|
||||
span,
|
||||
base_def,
|
||||
opt_self_ty,
|
||||
base_path_ref_id,
|
||||
base_segments,
|
||||
permit_variants);
|
||||
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
|
||||
|
||||
// If any associated type segments remain, attempt to resolve them.
|
||||
let (mut ty, mut def) = (base_ty, base_def);
|
||||
for segment in assoc_segments {
|
||||
debug!("finish_resolving_def_to_ty: segment={:?}", segment);
|
||||
// This is pretty bad (it will fail except for T::A and Self::A).
|
||||
let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
|
||||
ty = new_ty;
|
||||
def = new_def;
|
||||
|
||||
if def == Def::Err {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(ty, def)
|
||||
}
|
||||
|
||||
/// Parses the programmer's textual representation of a type into our
|
||||
/// internal notion of a type.
|
||||
pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
|
||||
|
|
@ -1701,26 +1648,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
tcx.types.err
|
||||
}
|
||||
}
|
||||
hir::TyPath(ref maybe_qself, ref path) => {
|
||||
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
|
||||
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
|
||||
let path_res = tcx.expect_resolution(ast_ty.id);
|
||||
let base_ty_end = path.segments.len() - path_res.depth;
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
|
||||
self.ast_ty_to_ty(rscope, &qself.ty)
|
||||
self.ast_ty_to_ty(rscope, qself)
|
||||
});
|
||||
let (ty, def) = self.finish_resolving_def_to_ty(rscope,
|
||||
ast_ty.span,
|
||||
path_res.base_def,
|
||||
opt_self_ty,
|
||||
ast_ty.id,
|
||||
&path.segments[..base_ty_end],
|
||||
&path.segments[base_ty_end..],
|
||||
false);
|
||||
self.def_to_ty(rscope,
|
||||
ast_ty.span,
|
||||
tcx.expect_def(ast_ty.id),
|
||||
opt_self_ty,
|
||||
ast_ty.id,
|
||||
&path.segments,
|
||||
false)
|
||||
}
|
||||
hir::TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
||||
debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
|
||||
let ty = self.ast_ty_to_ty(rscope, qself);
|
||||
|
||||
let def = tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
|
||||
let (ty, def) = self.associated_path_def_to_ty(ast_ty.span, ty, def, segment);
|
||||
|
||||
// Write back the new resolution.
|
||||
if path_res.depth != 0 {
|
||||
tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
|
||||
}
|
||||
tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
|
||||
|
||||
ty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,15 +148,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
typ
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected)
|
||||
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected)
|
||||
}
|
||||
PatKind::Path(ref opt_qself, ref path) => {
|
||||
let opt_qself_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
|
||||
self.check_pat_path(pat, opt_qself_ty, path, expected)
|
||||
PatKind::Path(ref qpath) => {
|
||||
self.check_pat_path(pat, qpath, expected)
|
||||
}
|
||||
PatKind::Struct(ref path, ref fields, etc) => {
|
||||
self.check_pat_struct(pat, path, fields, etc, expected)
|
||||
PatKind::Struct(ref qpath, ref fields, etc) => {
|
||||
self.check_pat_struct(pat, qpath, fields, etc, expected)
|
||||
}
|
||||
PatKind::Tuple(ref elements, ddpos) => {
|
||||
let mut expected_len = elements.len();
|
||||
|
|
@ -496,13 +495,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn check_pat_struct(&self,
|
||||
pat: &'gcx hir::Pat,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
fields: &'gcx [Spanned<hir::FieldPat>],
|
||||
etc: bool,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx>
|
||||
{
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) {
|
||||
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
|
||||
variant_ty
|
||||
} else {
|
||||
for field in fields {
|
||||
|
|
@ -521,20 +520,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn check_pat_path(&self,
|
||||
pat: &hir::Pat,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx>
|
||||
{
|
||||
let tcx = self.tcx;
|
||||
let report_unexpected_def = |def: Def| {
|
||||
span_err!(tcx.sess, pat.span, E0533,
|
||||
"expected unit struct/variant or constant, found {} `{}`",
|
||||
def.kind_name(), path);
|
||||
def.kind_name(), qpath);
|
||||
};
|
||||
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
|
||||
pat.id, pat.span);
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
|
||||
match def {
|
||||
Def::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
|
|
@ -558,7 +555,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn check_pat_tuple_struct(&self,
|
||||
pat: &hir::Pat,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
subpats: &'gcx [P<hir::Pat>],
|
||||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx>
|
||||
|
|
@ -571,14 +568,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
let report_unexpected_def = |def: Def| {
|
||||
let msg = format!("expected tuple struct/variant, found {} `{}`",
|
||||
def.kind_name(), path);
|
||||
def.kind_name(), qpath);
|
||||
struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
|
||||
.span_label(pat.span, &format!("not a tuple variant or struct")).emit();
|
||||
on_error();
|
||||
};
|
||||
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
|
||||
let variant = match def {
|
||||
Def::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ use syntax_pos::Span;
|
|||
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::hir;
|
||||
use rustc::hir::Expr_;
|
||||
|
||||
use std::cell;
|
||||
use std::cmp::Ordering;
|
||||
|
|
@ -210,7 +209,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if let Some(expr) = rcvr_expr {
|
||||
if let Ok(expr_string) = tcx.sess.codemap().span_to_snippet(expr.span) {
|
||||
report_function!(expr.span, expr_string);
|
||||
} else if let Expr_::ExprPath(_, path) = expr.node.clone() {
|
||||
} else if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = expr.node {
|
||||
if let Some(segment) = path.segments.last() {
|
||||
report_function!(expr.span, segment.name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3301,10 +3301,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn check_struct_path(&self,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
node_id: ast::NodeId)
|
||||
-> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> {
|
||||
let (def, ty) = self.finish_resolving_struct_path(path, node_id);
|
||||
let path_span = match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.span,
|
||||
hir::QPath::TypeRelative(ref qself, _) => qself.span
|
||||
};
|
||||
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, node_id);
|
||||
let variant = match def {
|
||||
Def::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
|
|
@ -3324,7 +3328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Def::AssociatedTy(..) | Def::SelfTy(..)
|
||||
if !self.tcx.sess.features.borrow().more_struct_aliases => {
|
||||
emit_feature_err(&self.tcx.sess.parse_sess,
|
||||
"more_struct_aliases", path.span, GateIssue::Language,
|
||||
"more_struct_aliases", path_span, GateIssue::Language,
|
||||
"`Self` and associated types in struct \
|
||||
expressions and patterns are unstable");
|
||||
}
|
||||
|
|
@ -3342,17 +3346,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
if let Some((variant, did, substs)) = variant {
|
||||
// Check bounds on type arguments used in the path.
|
||||
let bounds = self.instantiate_bounds(path.span, did, substs);
|
||||
let cause = traits::ObligationCause::new(path.span, self.body_id,
|
||||
let bounds = self.instantiate_bounds(path_span, did, substs);
|
||||
let cause = traits::ObligationCause::new(path_span, self.body_id,
|
||||
traits::ItemObligation(did));
|
||||
self.add_obligations_for_parameters(cause, &bounds);
|
||||
|
||||
Some((variant, ty))
|
||||
} else {
|
||||
struct_span_err!(self.tcx.sess, path.span, E0071,
|
||||
struct_span_err!(self.tcx.sess, path_span, E0071,
|
||||
"expected struct, variant or union type, found {}",
|
||||
ty.sort_string(self.tcx))
|
||||
.span_label(path.span, &format!("not a struct"))
|
||||
.span_label(path_span, &format!("not a struct"))
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
|
|
@ -3360,19 +3364,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn check_expr_struct(&self,
|
||||
expr: &hir::Expr,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
fields: &'gcx [hir::Field],
|
||||
base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
|
||||
{
|
||||
// Find the relevant variant
|
||||
let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id) {
|
||||
let (variant, struct_ty) =
|
||||
if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) {
|
||||
variant_ty
|
||||
} else {
|
||||
self.check_struct_fields_on_error(fields, base_expr);
|
||||
return self.tcx.types.err;
|
||||
};
|
||||
|
||||
self.check_expr_struct_fields(struct_ty, path.span, variant, fields,
|
||||
let path_span = match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.span,
|
||||
hir::QPath::TypeRelative(ref qself, _) => qself.span
|
||||
};
|
||||
|
||||
self.check_expr_struct_fields(struct_ty, path_span, variant, fields,
|
||||
base_expr.is_none());
|
||||
if let &Some(ref base_expr) = base_expr {
|
||||
self.check_expr_has_type(base_expr, struct_ty);
|
||||
|
|
@ -3590,9 +3600,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
tcx.mk_ref(region, tm)
|
||||
}
|
||||
}
|
||||
hir::ExprPath(ref opt_qself, ref path) => {
|
||||
let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
|
||||
hir::ExprPath(ref qpath) => {
|
||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath,
|
||||
expr.id, expr.span);
|
||||
let ty = if def != Def::Err {
|
||||
self.instantiate_value_path(segments, opt_ty, def, expr.span, id)
|
||||
|
|
@ -3930,8 +3939,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
tuple
|
||||
}
|
||||
}
|
||||
hir::ExprStruct(ref path, ref fields, ref base_expr) => {
|
||||
self.check_expr_struct(expr, path, fields, base_expr)
|
||||
hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
|
||||
self.check_expr_struct(expr, qpath, fields, base_expr)
|
||||
}
|
||||
hir::ExprField(ref base, ref field) => {
|
||||
self.check_field(expr, lvalue_pref, &base, field)
|
||||
|
|
@ -3999,72 +4008,75 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
|
||||
// The newly resolved definition is written into `def_map`.
|
||||
fn finish_resolving_struct_path(&self,
|
||||
path: &hir::Path,
|
||||
qpath: &hir::QPath,
|
||||
path_span: Span,
|
||||
node_id: ast::NodeId)
|
||||
-> (Def, Ty<'tcx>)
|
||||
{
|
||||
let path_res = self.tcx.expect_resolution(node_id);
|
||||
let base_ty_end = path.segments.len() - path_res.depth;
|
||||
let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span,
|
||||
path_res.base_def,
|
||||
None,
|
||||
node_id,
|
||||
&path.segments[..base_ty_end],
|
||||
&path.segments[base_ty_end..],
|
||||
true);
|
||||
// Write back the new resolution.
|
||||
if path_res.depth != 0 {
|
||||
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(ref maybe_qself, ref path) => {
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
|
||||
let def = self.tcx.expect_def(node_id);
|
||||
let ty = AstConv::def_to_ty(self, self,
|
||||
path.span,
|
||||
def,
|
||||
opt_self_ty,
|
||||
node_id,
|
||||
&path.segments,
|
||||
true);
|
||||
(def, ty)
|
||||
}
|
||||
hir::QPath::TypeRelative(ref qself, ref segment) => {
|
||||
let ty = self.to_ty(qself);
|
||||
|
||||
let def = self.tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
|
||||
let (ty, def) = AstConv::associated_path_def_to_ty(self, path_span,
|
||||
ty, def, segment);
|
||||
|
||||
// Write back the new resolution.
|
||||
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
|
||||
|
||||
(def, ty)
|
||||
}
|
||||
}
|
||||
(def, ty)
|
||||
}
|
||||
|
||||
// Resolve associated value path into a base type and associated constant or method definition.
|
||||
// The newly resolved definition is written into `def_map`.
|
||||
pub fn resolve_ty_and_def_ufcs<'b>(&self,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
path: &'b hir::Path,
|
||||
qpath: &'b hir::QPath,
|
||||
node_id: ast::NodeId,
|
||||
span: Span)
|
||||
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
|
||||
{
|
||||
let path_res = self.tcx.expect_resolution(node_id);
|
||||
if path_res.depth == 0 {
|
||||
// If fully resolved already, we don't have to do anything.
|
||||
(path_res.base_def, opt_self_ty, &path.segments)
|
||||
} else {
|
||||
// Try to resolve everything except for the last segment as a type.
|
||||
let ty_segments = path.segments.split_last().unwrap().1;
|
||||
let base_ty_end = path.segments.len() - path_res.depth;
|
||||
let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
|
||||
path_res.base_def,
|
||||
opt_self_ty,
|
||||
node_id,
|
||||
&ty_segments[..base_ty_end],
|
||||
&ty_segments[base_ty_end..],
|
||||
false);
|
||||
|
||||
// Resolve an associated constant or method on the previously resolved type.
|
||||
let item_segment = path.segments.last().unwrap();
|
||||
let item_name = item_segment.name;
|
||||
let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
|
||||
Ok(def) => def,
|
||||
Err(error) => {
|
||||
let def = match error {
|
||||
method::MethodError::PrivateMatch(def) => def,
|
||||
_ => Def::Err,
|
||||
};
|
||||
if item_name != keywords::Invalid.name() {
|
||||
self.report_method_error(span, ty, item_name, None, error);
|
||||
}
|
||||
def
|
||||
let (ty, item_segment) = match *qpath {
|
||||
hir::QPath::Resolved(ref opt_qself, ref path) => {
|
||||
return (self.tcx.expect_def(node_id),
|
||||
opt_qself.as_ref().map(|qself| self.to_ty(qself)),
|
||||
&path.segments[..]);
|
||||
}
|
||||
hir::QPath::TypeRelative(ref qself, ref segment) => {
|
||||
(self.to_ty(qself), segment)
|
||||
}
|
||||
};
|
||||
let item_name = item_segment.name;
|
||||
let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
|
||||
Ok(def) => def,
|
||||
Err(error) => {
|
||||
let def = match error {
|
||||
method::MethodError::PrivateMatch(def) => def,
|
||||
_ => Def::Err,
|
||||
};
|
||||
if item_name != keywords::Invalid.name() {
|
||||
self.report_method_error(span, ty, item_name, None, error);
|
||||
}
|
||||
};
|
||||
def
|
||||
}
|
||||
};
|
||||
|
||||
// Write back the new resolution.
|
||||
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
|
||||
(def, Some(ty), slice::ref_slice(item_segment))
|
||||
}
|
||||
// Write back the new resolution.
|
||||
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
|
||||
(def, Some(ty), slice::ref_slice(&**item_segment))
|
||||
}
|
||||
|
||||
pub fn check_decl_initializer(&self,
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> {
|
|||
debug!("regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
|
||||
expr, self.repeating_scope);
|
||||
match expr.node {
|
||||
hir::ExprPath(..) => {
|
||||
hir::ExprPath(_) => {
|
||||
self.fcx.opt_node_ty_substs(expr.id, |item_substs| {
|
||||
let origin = infer::ParameterOrigin::Path;
|
||||
self.substs_wf_in_scope(origin, &item_substs.substs, expr.span, expr_region);
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
param_id: ast::NodeId)
|
||||
-> bool
|
||||
{
|
||||
if let hir::TyPath(None, _) = ast_ty.node {
|
||||
if let hir::TyPath(hir::QPath::Resolved(None, _)) = ast_ty.node {
|
||||
let path_res = tcx.expect_resolution(ast_ty.id);
|
||||
match path_res.base_def {
|
||||
Def::SelfTy(Some(def_id), None) |
|
||||
|
|
|
|||
|
|
@ -1727,7 +1727,7 @@ impl Clean<Type> for hir::Ty {
|
|||
FixedVector(box ty.clean(cx), n)
|
||||
},
|
||||
TyTup(ref tys) => Tuple(tys.clean(cx)),
|
||||
TyPath(None, ref path) => {
|
||||
TyPath(hir::QPath::Resolved(None, ref path)) => {
|
||||
let def = cx.tcx.expect_def(self.id);
|
||||
if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
|
||||
return new_ty;
|
||||
|
|
@ -1766,7 +1766,7 @@ impl Clean<Type> for hir::Ty {
|
|||
}
|
||||
resolve_type(cx, path.clean(cx), self.id)
|
||||
}
|
||||
TyPath(Some(ref qself), ref p) => {
|
||||
TyPath(hir::QPath::Resolved(Some(ref qself), ref p)) => {
|
||||
let mut segments: Vec<_> = p.segments.clone().into();
|
||||
segments.pop();
|
||||
let trait_path = hir::Path {
|
||||
|
|
@ -1776,7 +1776,19 @@ impl Clean<Type> for hir::Ty {
|
|||
};
|
||||
Type::QPath {
|
||||
name: p.segments.last().unwrap().name.clean(cx),
|
||||
self_type: box qself.ty.clean(cx),
|
||||
self_type: box qself.clean(cx),
|
||||
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
|
||||
}
|
||||
}
|
||||
TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
||||
let trait_path = hir::Path {
|
||||
span: self.span,
|
||||
global: false,
|
||||
segments: vec![].into(),
|
||||
};
|
||||
Type::QPath {
|
||||
name: segment.name.clean(cx),
|
||||
self_type: box qself.clean(cx),
|
||||
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
|
||||
}
|
||||
}
|
||||
|
|
@ -2263,11 +2275,20 @@ impl Clean<PathSegment> for hir::PathSegment {
|
|||
}
|
||||
}
|
||||
|
||||
fn path_to_string(p: &hir::Path) -> String {
|
||||
fn qpath_to_string(p: &hir::QPath) -> String {
|
||||
let (segments, global) = match *p {
|
||||
hir::QPath::Resolved(_, ref path) => {
|
||||
(&path.segments, path.global)
|
||||
}
|
||||
hir::QPath::TypeRelative(_, ref segment) => {
|
||||
return segment.name.to_string()
|
||||
}
|
||||
};
|
||||
|
||||
let mut s = String::new();
|
||||
let mut first = true;
|
||||
for i in p.segments.iter().map(|x| x.name.as_str()) {
|
||||
if !first || p.global {
|
||||
for i in segments.iter().map(|x| x.name.as_str()) {
|
||||
if !first || global {
|
||||
s.push_str("::");
|
||||
} else {
|
||||
first = false;
|
||||
|
|
@ -2725,17 +2746,15 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
|||
match p.node {
|
||||
PatKind::Wild => "_".to_string(),
|
||||
PatKind::Binding(_, ref p, _) => p.node.to_string(),
|
||||
PatKind::TupleStruct(ref p, ..) | PatKind::Path(None, ref p) => path_to_string(p),
|
||||
PatKind::Path(..) => panic!("tried to get argument name from qualified PatKind::Path, \
|
||||
which is not allowed in function arguments"),
|
||||
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
|
||||
PatKind::Struct(ref name, ref fields, etc) => {
|
||||
format!("{} {{ {}{} }}", path_to_string(name),
|
||||
format!("{} {{ {}{} }}", qpath_to_string(name),
|
||||
fields.iter().map(|&Spanned { node: ref fp, .. }|
|
||||
format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
|
||||
.collect::<Vec<String>>().join(", "),
|
||||
if etc { ", ..." } else { "" }
|
||||
)
|
||||
},
|
||||
}
|
||||
PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
|
||||
.collect::<Vec<String>>().join(", ")),
|
||||
PatKind::Box(ref p) => name_from_pat(&**p),
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ impl S {
|
|||
fn main() {
|
||||
if let C1(..) = 0 {} //~ ERROR expected tuple struct/variant, found constant `C1`
|
||||
if let S::C2(..) = 0 {}
|
||||
//~^ ERROR expected tuple struct/variant, found associated constant `S::C2`
|
||||
//~^ ERROR expected tuple struct/variant, found associated constant `<S>::C2`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ impl MyTrait for Foo {}
|
|||
|
||||
fn main() {
|
||||
match 0u32 {
|
||||
Foo::bar => {} //~ ERROR expected unit struct/variant or constant, found method `Foo::bar`
|
||||
Foo::bar => {}
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
|
||||
}
|
||||
match 0u32 {
|
||||
<Foo>::bar => {} //~ ERROR expected unit struct/variant or constant, found method `bar`
|
||||
<Foo>::bar => {}
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
|
||||
}
|
||||
match 0u32 {
|
||||
<Foo>::trait_bar => {}
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `trait_bar`
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `<Foo>::trait_bar`
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl S {
|
|||
fn main() {
|
||||
match 10 {
|
||||
<S as Tr>::A::f::<u8> => {}
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `Tr::A::f<u8>`
|
||||
//~^ ERROR expected unit struct/variant or constant, found method `<<S as Tr>::A>::f<u8>`
|
||||
0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
// except according to those terms.
|
||||
|
||||
pub trait Foo<A=Self> {
|
||||
fn foo();
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
pub trait Bar<X=usize, A=Self> {
|
||||
fn foo();
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pub fn bar() ({
|
|||
|
||||
|
||||
(($crate::fmt::format as
|
||||
fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((::std::fmt::Arguments::new_v1
|
||||
fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1
|
||||
as
|
||||
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})(({
|
||||
static __STATIC_FMTSTR:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue