rustc_resolve: use DefAssociatedTy for TyQPath.
This commit is contained in:
parent
9a69378e8b
commit
326711e9bd
@ -3563,8 +3563,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
match ty.node {
|
||||
// Like path expressions, the interpretation of path types depends
|
||||
// on whether the path has multiple elements in it or not.
|
||||
TyPath(_) | TyQPath(_) => {
|
||||
let mut path_from_qpath;
|
||||
let path = match ty.node {
|
||||
TyPath(ref path) => path,
|
||||
TyQPath(ref qpath) => {
|
||||
self.resolve_type(&*qpath.self_type);
|
||||
|
||||
// Just make sure the trait is valid, don't record a def.
|
||||
self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath);
|
||||
self.def_map.borrow_mut().remove(&ty.id);
|
||||
|
||||
path_from_qpath = qpath.trait_path.clone();
|
||||
path_from_qpath.segments.push(qpath.item_path.clone());
|
||||
&path_from_qpath
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
TyPath(ref path) => {
|
||||
// This is a path in the type namespace. Walk through scopes
|
||||
// looking for it.
|
||||
let mut result_def = None;
|
||||
@ -3609,7 +3625,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.record_def(ty.id, def);
|
||||
}
|
||||
None => {
|
||||
let msg = format!("use of undeclared type name `{}`",
|
||||
let kind = match ty.node {
|
||||
TyQPath(_) => "associated type",
|
||||
_ => "type name"
|
||||
};
|
||||
let msg = format!("use of undeclared {} `{}`", kind,
|
||||
self.path_names_to_string(path));
|
||||
self.resolve_error(ty.span, &msg[..]);
|
||||
}
|
||||
@ -3621,17 +3641,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter);
|
||||
}
|
||||
|
||||
TyQPath(ref qpath) => {
|
||||
self.resolve_type(&*qpath.self_type);
|
||||
self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath);
|
||||
for ty in qpath.item_path.parameters.types() {
|
||||
self.resolve_type(&**ty);
|
||||
}
|
||||
for binding in qpath.item_path.parameters.bindings() {
|
||||
self.resolve_type(&*binding.ty);
|
||||
}
|
||||
}
|
||||
|
||||
TyPolyTraitRef(ref bounds) => {
|
||||
self.resolve_type_parameter_bounds(bounds, TraitObject);
|
||||
visit::walk_ty(self, ty);
|
||||
|
@ -606,9 +606,10 @@ pub fn instantiate_trait_ref<'tcx>(
|
||||
def::DefTrait(trait_def_id) => {
|
||||
let trait_ref = ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
path.span,
|
||||
trait_def_id,
|
||||
self_ty,
|
||||
path,
|
||||
path.segments.last().unwrap(),
|
||||
projections);
|
||||
if let Some(id) = impl_id {
|
||||
this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
|
||||
@ -637,9 +638,10 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
|
||||
let mut tmp = Vec::new();
|
||||
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
|
||||
&shifted_rscope,
|
||||
path.span,
|
||||
trait_def_id,
|
||||
None,
|
||||
path,
|
||||
path.segments.last().unwrap(),
|
||||
Some(&mut tmp)));
|
||||
projections.extend(tmp.into_iter().map(ty::Binder));
|
||||
trait_ref
|
||||
@ -648,24 +650,25 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
|
||||
fn ast_path_to_trait_ref<'a,'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
path: &ast::Path,
|
||||
trait_segment: &ast::PathSegment,
|
||||
mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
|
||||
-> Rc<ty::TraitRef<'tcx>>
|
||||
{
|
||||
debug!("ast_path_to_trait_ref {:?}", path);
|
||||
debug!("ast_path_to_trait_ref {:?}", trait_segment);
|
||||
let trait_def = this.get_trait_def(trait_def_id);
|
||||
|
||||
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
|
||||
let (regions, types, assoc_bindings) = match trait_segment.parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
// For now, require that parenthetical notation be used
|
||||
// only with `Fn()` etc.
|
||||
if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
|
||||
span_err!(this.tcx().sess, path.span, E0215,
|
||||
span_err!(this.tcx().sess, span, E0215,
|
||||
"angle-bracket notation is not stable when \
|
||||
used with the `Fn` family of traits, use parentheses");
|
||||
span_help!(this.tcx().sess, path.span,
|
||||
span_help!(this.tcx().sess, span,
|
||||
"add `#![feature(unboxed_closures)]` to \
|
||||
the crate attributes to enable");
|
||||
}
|
||||
@ -676,10 +679,10 @@ fn ast_path_to_trait_ref<'a,'tcx>(
|
||||
// For now, require that parenthetical notation be used
|
||||
// only with `Fn()` etc.
|
||||
if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
|
||||
span_err!(this.tcx().sess, path.span, E0216,
|
||||
span_err!(this.tcx().sess, span, E0216,
|
||||
"parenthetical notation is only stable when \
|
||||
used with the `Fn` family of traits");
|
||||
span_help!(this.tcx().sess, path.span,
|
||||
span_help!(this.tcx().sess, span,
|
||||
"add `#![feature(unboxed_closures)]` to \
|
||||
the crate attributes to enable");
|
||||
}
|
||||
@ -689,7 +692,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
|
||||
};
|
||||
|
||||
let substs = create_substs_for_ast_path(this,
|
||||
path.span,
|
||||
span,
|
||||
&trait_def.generics,
|
||||
self_ty,
|
||||
types,
|
||||
@ -1047,33 +1050,42 @@ fn trait_defines_associated_type_named(this: &AstConv,
|
||||
|
||||
fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_ty: &ast::Ty, // the TyQPath
|
||||
qpath: &ast::QPath)
|
||||
span: Span,
|
||||
opt_self_ty: Option<&ast::Ty>,
|
||||
trait_def_id: ast::DefId,
|
||||
trait_segment: &ast::PathSegment,
|
||||
item_segment: &ast::PathSegment)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
debug!("qpath_to_ty(ast_ty={})",
|
||||
ast_ty.repr(this.tcx()));
|
||||
let tcx = this.tcx();
|
||||
|
||||
let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
|
||||
let self_ty = if let Some(ty) = opt_self_ty {
|
||||
ast_ty_to_ty(this, rscope, ty)
|
||||
} else {
|
||||
let path_str = ty::item_path_str(tcx, trait_def_id);
|
||||
span_err!(tcx.sess, span, E0223,
|
||||
"ambiguous associated type; specify the type using the syntax \
|
||||
`<Type as {}>::{}`",
|
||||
path_str, &token::get_ident(item_segment.identifier));
|
||||
return tcx.types.err;
|
||||
};
|
||||
|
||||
debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
|
||||
debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
|
||||
|
||||
let trait_ref = instantiate_trait_ref(this,
|
||||
let trait_ref = ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
&qpath.trait_path,
|
||||
ast_ty.id,
|
||||
None,
|
||||
Some(self_type),
|
||||
span,
|
||||
trait_def_id,
|
||||
Some(self_ty),
|
||||
trait_segment,
|
||||
None);
|
||||
|
||||
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
|
||||
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
|
||||
|
||||
// `<T as Trait>::U<V>` shouldn't parse right now.
|
||||
assert!(qpath.item_path.parameters.is_empty());
|
||||
assert!(item_segment.parameters.is_empty());
|
||||
|
||||
return this.projected_ty(ast_ty.span,
|
||||
trait_ref,
|
||||
qpath.item_path.identifier.name);
|
||||
this.projected_ty(span, trait_ref, item_segment.identifier.name)
|
||||
}
|
||||
|
||||
/// Convert a type supplied as value for a type argument from AST into our
|
||||
@ -1189,13 +1201,17 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
ast::TyPolyTraitRef(ref bounds) => {
|
||||
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
|
||||
}
|
||||
ast::TyPath(ref path) => {
|
||||
ast::TyPath(_) | ast::TyQPath(_) => {
|
||||
let simple_path = |&:| match ast_ty.node {
|
||||
ast::TyPath(ref path) => path,
|
||||
_ => tcx.sess.span_bug(ast_ty.span, "expected non-qualified path")
|
||||
};
|
||||
let a_def = match tcx.def_map.borrow().get(&ast_ty.id) {
|
||||
None => {
|
||||
tcx.sess
|
||||
.span_bug(ast_ty.span,
|
||||
&format!("unbound path {}",
|
||||
path.repr(tcx)))
|
||||
ast_ty.repr(tcx)))
|
||||
}
|
||||
Some(&d) => d
|
||||
};
|
||||
@ -1208,24 +1224,24 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
let trait_ref = object_path_to_poly_trait_ref(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
path,
|
||||
simple_path(),
|
||||
&mut projection_bounds);
|
||||
|
||||
trait_ref_to_object_type(this, rscope, path.span,
|
||||
trait_ref_to_object_type(this, rscope, ast_ty.span,
|
||||
trait_ref, projection_bounds, &[])
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
ast_path_to_ty(this, rscope, did, path).ty
|
||||
ast_path_to_ty(this, rscope, did, simple_path()).ty
|
||||
}
|
||||
def::DefTyParam(space, index, _, name) => {
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS);
|
||||
ty::mk_param(tcx, space, index, name)
|
||||
}
|
||||
def::DefSelfTy(_) => {
|
||||
// n.b.: resolve guarantees that the this type only appears in a
|
||||
// trait, which we rely upon in various places when creating
|
||||
// substs
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS);
|
||||
ty::mk_self_type(tcx)
|
||||
}
|
||||
def::DefMod(id) => {
|
||||
@ -1236,20 +1252,20 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
def::DefPrimTy(_) => {
|
||||
panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
|
||||
}
|
||||
def::DefAssociatedTy(trait_id, _) => {
|
||||
let path_str = ty::item_path_str(tcx, trait_id);
|
||||
span_err!(tcx.sess, ast_ty.span, E0223,
|
||||
"ambiguous associated \
|
||||
type; specify the type \
|
||||
using the syntax `<Type \
|
||||
as {}>::{}`",
|
||||
path_str,
|
||||
&token::get_ident(
|
||||
path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier));
|
||||
this.tcx().types.err
|
||||
def::DefAssociatedTy(trait_did, _) => {
|
||||
let (opt_self_ty, trait_segment, item_segment) = match ast_ty.node {
|
||||
ast::TyQPath(ref qpath) => {
|
||||
(Some(&*qpath.self_type), qpath.trait_path.segments.last().unwrap(),
|
||||
&qpath.item_path)
|
||||
}
|
||||
ast::TyPath(ref path) => {
|
||||
(None, &path.segments[path.segments.len()-2],
|
||||
path.segments.last().unwrap())
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty,
|
||||
trait_did, trait_segment, item_segment)
|
||||
}
|
||||
def::DefAssociatedPath(provenance, assoc_ident) => {
|
||||
associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
|
||||
@ -1262,9 +1278,6 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyQPath(ref qpath) => {
|
||||
qpath_to_ty(this, rscope, ast_ty, &**qpath)
|
||||
}
|
||||
ast::TyFixedLengthVec(ref ty, ref e) => {
|
||||
match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
|
||||
Ok(ref r) => {
|
||||
|
@ -1499,6 +1499,13 @@ impl Clean<Type> for ast::Ty {
|
||||
TyPath(ref p) => {
|
||||
resolve_type(cx, p.clean(cx), self.id)
|
||||
}
|
||||
TyQPath(ref qp) => {
|
||||
Type::QPath {
|
||||
name: qp.item_path.identifier.clean(cx),
|
||||
self_type: box qp.self_type.clean(cx),
|
||||
trait_: box resolve_type(cx, qp.trait_path.clean(cx), self.id)
|
||||
}
|
||||
}
|
||||
TyObjectSum(ref lhs, ref bounds) => {
|
||||
let lhs_ty = lhs.clean(cx);
|
||||
match lhs_ty {
|
||||
@ -1512,7 +1519,6 @@ impl Clean<Type> for ast::Ty {
|
||||
}
|
||||
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
||||
TyParen(ref ty) => ty.clean(cx),
|
||||
TyQPath(ref qp) => qp.clean(cx),
|
||||
TyPolyTraitRef(ref bounds) => {
|
||||
PolyTraitRef(bounds.clean(cx))
|
||||
},
|
||||
@ -1624,16 +1630,6 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Type> for ast::QPath {
|
||||
fn clean(&self, cx: &DocContext) -> Type {
|
||||
Type::QPath {
|
||||
name: self.item_path.identifier.clean(cx),
|
||||
self_type: box self.self_type.clean(cx),
|
||||
trait_: box resolve_type(cx, self.trait_path.clean(cx), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum StructField {
|
||||
HiddenStructField, // inserted later by strip passes
|
||||
|
@ -15,18 +15,11 @@ trait From<Src> {
|
||||
}
|
||||
|
||||
trait To {
|
||||
// This is a typo, the return type should be `<Dst as From<Self>>::Output`
|
||||
fn to<Dst: From<Self>>(
|
||||
self
|
||||
//~^ error: the trait `core::marker::Sized` is not implemented
|
||||
) ->
|
||||
fn to<Dst: From<Self>>(self) ->
|
||||
<Dst as From<Self>>::Dst
|
||||
//~^ error: the trait `core::marker::Sized` is not implemented
|
||||
//~^ ERROR use of undeclared associated type `From::Dst`
|
||||
{
|
||||
From::from(
|
||||
//~^ error: the trait `core::marker::Sized` is not implemented
|
||||
self
|
||||
)
|
||||
From::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user