]> git.lizzy.rs Git - rust.git/commitdiff
rustc_resolve: use DefAssociatedTy for TyQPath.
authorEduard Burtescu <edy.burt@gmail.com>
Sat, 31 Jan 2015 03:51:21 +0000 (05:51 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Tue, 24 Feb 2015 12:14:16 +0000 (14:14 +0200)
src/librustc_resolve/lib.rs
src/librustc_typeck/astconv.rs
src/librustdoc/clean/mod.rs
src/test/compile-fail/issue-19883.rs

index 1380e2367256dbdcf1c27808d304840db8ed60ea..914663e75814e059bd2436a30954442f38537c50 100644 (file)
@@ -3563,8 +3563,24 @@ fn resolve_type(&mut self, ty: &Ty) {
         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 @@ fn resolve_type(&mut self, ty: &Ty) {
                         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 @@ fn resolve_type(&mut self, ty: &Ty) {
                 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);
index 8b5cb1f97466656a3b07de0d64faeb327dd7b8d8..cf567f709f52a6f7dd0515336759b880f87c162c 100644 (file)
@@ -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) => {
index 8e08c5278d004609a6ea0931d969766cec88aca7..aff15761ae7755081b9f7f7c67ccfc3c7cc5c532 100644 (file)
@@ -1499,6 +1499,13 @@ fn clean(&self, cx: &DocContext) -> Type {
             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 @@ fn clean(&self, cx: &DocContext) -> Type {
             }
             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 @@ fn clean(&self, cx: &DocContext) -> Type {
     }
 }
 
-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
index bbc5ee6c8f36e336e453eb9c0920de56faf1e0fb..c6ff82364b3e7cd57c279b9e4772aab1d386c51f 100644 (file)
@@ -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)
     }
 }