Skip to content

Commit

Permalink
rustc_resolve: use DefAssociatedTy for TyQPath.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Feb 24, 2015
1 parent 9a69378 commit 326711e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 84 deletions.
35 changes: 22 additions & 13 deletions src/librustc_resolve/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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[..]);
}
Expand All @@ -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);
Expand Down
113 changes: 63 additions & 50 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
};
Expand All @@ -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) => {
Expand All @@ -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)
Expand All @@ -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) => {
Expand Down
18 changes: 7 additions & 11 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -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 {
Expand All @@ -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))
},
Expand Down Expand Up @@ -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
Expand Down
13 changes: 3 additions & 10 deletions src/test/compile-fail/issue-19883.rs
Expand Up @@ -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)
}
}

Expand Down

0 comments on commit 326711e

Please sign in to comment.