]> git.lizzy.rs Git - rust.git/commitdiff
Use partial path resolutions in expressions for UFCS desugaring.
authorEduard Burtescu <edy.burt@gmail.com>
Wed, 11 Feb 2015 07:33:49 +0000 (09:33 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Tue, 24 Feb 2015 12:16:01 +0000 (14:16 +0200)
src/librustc/middle/astconv_util.rs
src/librustc_resolve/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/test/compile-fail/issue-3973.rs
src/test/run-pass/const-polymorphic-paths.rs

index 621a231ed7d186304e7b861875c62560c70cc37a..1cd5a19d6788a2435558b918d17f2de5e44d26d0 100644 (file)
 use middle::def;
 use middle::ty::{self, Ty};
 use syntax::ast;
-use syntax::codemap::Span;
 use util::ppaux::Repr;
 
 pub const NO_REGIONS: uint = 1;
 pub const NO_TPS: uint = 2;
 
-pub fn check_path_args(tcx: &ty::ctxt,
-                       span: Span,
-                       segments: &[ast::PathSegment],
-                       flags: uint) {
-    if (flags & NO_TPS) != 0 {
-        if segments.iter().any(|s| s.parameters.has_types()) {
-            span_err!(tcx.sess, span, E0109,
-                "type parameters are not allowed on this type");
+pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
+    for segment in segments {
+        if (flags & NO_TPS) != 0 {
+            for typ in segment.parameters.types() {
+                span_err!(tcx.sess, typ.span, E0109,
+                          "type parameters are not allowed on this type");
+                break;
+            }
         }
-    }
 
-    if (flags & NO_REGIONS) != 0 {
-        if segments.iter().any(|s| s.parameters.has_lifetimes()) {
-            span_err!(tcx.sess, span, E0110,
-                "lifetime parameters are not allowed on this type");
+        if (flags & NO_REGIONS) != 0 {
+            for lifetime in segment.parameters.lifetimes() {
+                span_err!(tcx.sess, lifetime.span, E0110,
+                          "lifetime parameters are not allowed on this type");
+                break;
+            }
         }
     }
 }
 
 pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                           span: Span,
                            segments: &[ast::PathSegment],
                            nty: ast::PrimTy)
                            -> Ty<'tcx> {
-    check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
+    check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
     match nty {
         ast::TyBool => tcx.types.bool,
         ast::TyChar => tcx.types.char,
@@ -69,7 +68,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
             Some(&d) => d
         };
         if let def::DefPrimTy(nty) = def {
-            Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty))
+            Some(prim_ty_to_ty(tcx, &path.segments[], nty))
         } else {
             None
         }
index b85ac04cc9e239e9aa4ea987fdbb88794923785c..0c5236101cfb862e4ae915ae0550e1a2be9d97b7 100644 (file)
@@ -3018,7 +3018,7 @@ fn resolve_trait_reference(&mut self,
     }
 
     fn resolve_generics(&mut self, generics: &Generics) {
-        for type_parameter in &generics.ty_params {
+        for type_parameter in &*generics.ty_params {
             self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
         }
         for predicate in &generics.where_clause.predicates {
@@ -4083,16 +4083,35 @@ fn resolve_expr(&mut self, expr: &Expr) {
             // multiple elements in it or not.
 
             ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
-                if let ExprQPath(_) = expr.node {
+                let max_assoc_types = if let ExprQPath(_) = expr.node {
                     // Make sure the trait is valid.
                     let _ = self.resolve_trait_reference(expr.id, path, 1);
+                    1
+                } else {
+                    path.segments.len()
+                };
+
+                let mut result = self.with_no_errors(|this| {
+                    this.resolve_path(expr.id, path, 0, ValueNS, true)
+                });
+                for depth in 1..max_assoc_types {
+                    if result.is_some() {
+                        break;
+                    }
+                    self.with_no_errors(|this| {
+                        result = this.resolve_path(expr.id, path, depth, TypeNS, true);
+                    });
+                }
+                if let Some((DefMod(_), _, _)) = result {
+                    // A module is not a valid type or value.
+                    result = None;
                 }
 
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
-                match self.resolve_path(expr.id, path, 0, ValueNS, true) {
+                match result {
                     // Check if struct variant
-                    Some((DefVariant(_, _, true), _, _)) => {
+                    Some((DefVariant(_, _, true), _, 0)) => {
                         let path_name = self.path_names_to_string(path, 0);
                         self.resolve_error(expr.span,
                                 &format!("`{}` is a struct variant name, but \
@@ -4110,6 +4129,14 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         debug!("(resolving expr) resolved `{}`",
                                self.path_names_to_string(path, 0));
 
+                        // Partial resolutions will need the set of traits in scope,
+                        // so they can be completed during typeck.
+                        if def.2 != 0 {
+                            let method_name = path.segments.last().unwrap().identifier.name;
+                            let traits = self.search_for_traits_containing_method(method_name);
+                            self.trait_map.insert(expr.id, traits);
+                        }
+
                         self.record_def(expr.id, def);
                     }
                     None => {
@@ -4135,6 +4162,9 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
                             }
                             _ => {
+                                // Keep reporting some errors even if they're ignored above.
+                                self.resolve_path(expr.id, path, 0, ValueNS, true);
+
                                 let mut method_scope = false;
                                 self.value_ribs.iter().rev().all(|rib| {
                                     method_scope = match rib.kind {
index bc0986eff1f28521093a35c534bf4ad6beee6132..adbc4d546f1903ba30ee201462f6ecf866de6b06 100644 (file)
@@ -246,6 +246,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
     item_segment: &ast::PathSegment)
     -> Substs<'tcx>
@@ -265,12 +266,12 @@ pub fn ast_path_substs_for_ty<'tcx>(
 
     let (regions, types, assoc_bindings) = match item_segment.parameters {
         ast::AngleBracketedParameters(ref data) => {
-            convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             span_err!(tcx.sess, span, E0214,
                 "parenthesized parameters may only be used with a trait");
-            convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data)
+            convert_parenthesized_parameters(this, rscope, span, decl_generics, data)
         }
     };
 
@@ -278,12 +279,21 @@ pub fn ast_path_substs_for_ty<'tcx>(
 
     create_substs_for_ast_path(this,
                                span,
+                               param_mode,
                                decl_generics,
                                None,
                                types,
                                regions)
 }
 
+#[derive(PartialEq, Eq)]
+pub enum PathParamMode {
+    // Any path in a type context.
+    Explicit,
+    // The `module::Type` in `module::Type::method` in an expression.
+    Optional
+}
+
 fn create_region_substs<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
@@ -331,6 +341,7 @@ fn create_region_substs<'tcx>(
 fn create_substs_for_ast_path<'tcx>(
     this: &AstConv<'tcx>,
     span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types_provided: Vec<Ty<'tcx>>,
@@ -349,13 +360,21 @@ fn create_substs_for_ast_path<'tcx>(
 
     // Convert the type parameters supplied by the user.
     let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
-    let supplied_ty_param_count = types_provided.len();
     let formal_ty_param_count = ty_param_defs.len();
     let required_ty_param_count = ty_param_defs.iter()
                                                .take_while(|x| x.default.is_none())
                                                .count();
 
-    let mut type_substs = types_provided;
+    // Fill with `ty_infer` if no params were specified, as long as
+    // they were optional (e.g. paths inside expressions).
+    let mut type_substs = if param_mode == PathParamMode::Optional &&
+                             types_provided.is_empty() {
+        (0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect()
+    } else {
+        types_provided
+    };
+
+    let supplied_ty_param_count = type_substs.len();
     check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
                               required_ty_param_count, formal_ty_param_count);
 
@@ -415,7 +434,7 @@ fn create_substs_for_ast_path<'tcx>(
         }
     }
 
-    return substs;
+    substs
 }
 
 struct ConvertedBinding<'tcx> {
@@ -607,6 +626,7 @@ pub fn instantiate_trait_ref<'tcx>(
             let trait_ref = ast_path_to_trait_ref(this,
                                                   rscope,
                                                   path.span,
+                                                  PathParamMode::Explicit,
                                                   trait_def_id,
                                                   self_ty,
                                                   path.segments.last().unwrap(),
@@ -627,6 +647,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
     trait_segment: &ast::PathSegment,
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
@@ -640,6 +661,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
                                                      &shifted_rscope,
                                                      span,
+                                                     param_mode,
                                                      trait_def_id,
                                                      None,
                                                      trait_segment,
@@ -652,6 +674,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
     trait_segment: &ast::PathSegment,
@@ -674,7 +697,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                             the crate attributes to enable");
             }
 
-            convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
@@ -688,12 +711,13 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                             the crate attributes to enable");
             }
 
-            convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data)
         }
     };
 
     let substs = create_substs_for_ast_path(this,
                                             span,
+                                            param_mode,
                                             &trait_def.generics,
                                             self_ty,
                                             types,
@@ -830,6 +854,7 @@ fn ast_path_to_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
+    param_mode: PathParamMode,
     did: ast::DefId,
     item_segment: &ast::PathSegment)
     -> Ty<'tcx>
@@ -839,7 +864,9 @@ fn ast_path_to_ty<'tcx>(
         ty: decl_ty
     } = this.get_item_type_scheme(did);
 
-    let substs = ast_path_substs_for_ty(this, rscope, span, &generics, item_segment);
+    let substs = ast_path_substs_for_ty(this, rscope,
+                                        span, param_mode,
+                                        &generics, item_segment);
 
     // FIXME(#12938): This is a hack until we have full support for DST.
     if Some(did) == this.tcx().lang_items.owned_box() {
@@ -878,6 +905,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                     let trait_ref = object_path_to_poly_trait_ref(this,
                                                                   rscope,
                                                                   path.span,
+                                                                  PathParamMode::Explicit,
                                                                   trait_def_id,
                                                                   path.segments.last().unwrap(),
                                                                   &mut projection_bounds);
@@ -950,8 +978,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    -> (Ty<'tcx>, def::Def)
 {
     let tcx = this.tcx();
-    check_path_args(tcx, span, slice::ref_slice(item_segment),
-                    NO_TPS | NO_REGIONS);
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
     let assoc_name = item_segment.identifier.name;
 
     let ty_param_node_id = if let ty::ty_param(_) = ty.sty {
@@ -1043,7 +1070,8 @@ fn trait_defines_associated_type_named(this: &AstConv,
 fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
                      rscope: &RegionScope,
                      span: Span,
-                     opt_self_ty: Option<&ast::Ty>,
+                     param_mode: PathParamMode,
+                     opt_self_ty: Option<Ty<'tcx>>,
                      trait_def_id: ast::DefId,
                      trait_segment: &ast::PathSegment,
                      item_segment: &ast::PathSegment)
@@ -1051,11 +1079,10 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
 {
     let tcx = this.tcx();
 
-    check_path_args(tcx, span, slice::ref_slice(item_segment),
-                    NO_TPS | NO_REGIONS);
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
 
     let self_ty = if let Some(ty) = opt_self_ty {
-        ast_ty_to_ty(this, rscope, ty)
+        ty
     } else {
         let path_str = ty::item_path_str(tcx, trait_def_id);
         span_err!(tcx.sess, span, E0223,
@@ -1070,6 +1097,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
     let trait_ref = ast_path_to_trait_ref(this,
                                           rscope,
                                           span,
+                                          param_mode,
                                           trait_def_id,
                                           Some(self_ty),
                                           trait_segment,
@@ -1113,6 +1141,88 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
+pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
+                                        rscope: &RegionScope,
+                                        span: Span,
+                                        param_mode: PathParamMode,
+                                        def: &mut def::Def,
+                                        opt_self_ty: Option<Ty<'tcx>>,
+                                        segments: &[ast::PathSegment],
+                                        assoc_segments: &[ast::PathSegment])
+                                        -> Ty<'tcx> {
+    let tcx = this.tcx();
+
+    let base_ty = match *def {
+        def::DefTrait(trait_def_id) => {
+            // N.B. this case overlaps somewhat with
+            // TyObjectSum, see that fn for details
+            let mut projection_bounds = Vec::new();
+
+            let trait_ref = object_path_to_poly_trait_ref(this,
+                                                          rscope,
+                                                          span,
+                                                          param_mode,
+                                                          trait_def_id,
+                                                          segments.last().unwrap(),
+                                                          &mut projection_bounds);
+
+            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            trait_ref_to_object_type(this, rscope, span, trait_ref,
+                                     projection_bounds, &[])
+        }
+        def::DefTy(did, _) | def::DefStruct(did) => {
+            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            ast_path_to_ty(this, rscope, span,
+                           param_mode, did,
+                           segments.last().unwrap())
+        }
+        def::DefTyParam(space, index, _, name) => {
+            check_path_args(tcx, segments, 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, segments, NO_TPS | NO_REGIONS);
+            ty::mk_self_type(tcx)
+        }
+        def::DefAssociatedTy(trait_did, _) => {
+            check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS);
+            qpath_to_ty(this, rscope, span, param_mode,
+                        opt_self_ty, trait_did,
+                        &segments[segments.len()-2],
+                        segments.last().unwrap())
+        }
+        def::DefMod(id) => {
+            tcx.sess.span_bug(span,
+                              &format!("found module name used as a type: {}",
+                                       tcx.map.node_to_string(id.node)));
+        }
+        def::DefPrimTy(prim_ty) => {
+            prim_ty_to_ty(tcx, segments, prim_ty)
+        }
+        _ => {
+            span_fatal!(tcx.sess, span, E0248,
+                        "found value name used as a type: {:?}", *def);
+        }
+    };
+
+    // If any associated type segments remain, attempt to resolve them.
+    let mut ty = base_ty;
+    for segment in assoc_segments {
+        if ty.sty == ty::ty_err {
+            break;
+        }
+        // This is pretty bad (it will fail except for T::A and Self::A).
+        let (a_ty, a_def) = associated_path_def_to_ty(this, span,
+                                                      ty, *def, segment);
+        ty = a_ty;
+        *def = a_def;
+    }
+    ty
+}
+
 /// Parses the programmer's textual representation of a type into our
 /// internal notion of a type.
 pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
@@ -1201,81 +1311,18 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                 tcx.sess.span_bug(ast_ty.span,
                                   &format!("unbound path {}", ast_ty.repr(tcx)))
             };
-            let (base_def, max_depth) = result;
-            let span = ast_ty.span; // Could be more granular.
-            let segments = &path.segments[..path.segments.len()-max_depth];
-            let base_ty = match base_def {
-                def::DefTrait(trait_def_id) => {
-                    // N.B. this case overlaps somewhat with
-                    // TyObjectSum, see that fn for details
-                    let mut projection_bounds = Vec::new();
-
-                    let trait_ref = object_path_to_poly_trait_ref(this,
-                                                                  rscope,
-                                                                  span,
-                                                                  trait_def_id,
-                                                                  segments.last().unwrap(),
-                                                                  &mut projection_bounds);
-
-                    check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS);
-                    trait_ref_to_object_type(this, rscope, span, trait_ref,
-                                             projection_bounds, &[])
-                }
-                def::DefTy(did, _) | def::DefStruct(did) => {
-                    check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS);
-                    ast_path_to_ty(this, rscope, span, did, segments.last().unwrap())
-                }
-                def::DefTyParam(space, index, _, name) => {
-                    check_path_args(tcx, span, segments, 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, span, segments, NO_TPS | NO_REGIONS);
-                    ty::mk_self_type(tcx)
-                }
-                def::DefAssociatedTy(trait_did, _) => {
-                    let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
-                        Some(&*qpath.self_type)
-                    } else {
-                        None
-                    };
-                    check_path_args(tcx, span, &segments[..segments.len()-2],
-                                    NO_TPS | NO_REGIONS);
-                    qpath_to_ty(this, rscope, span, opt_self_ty, trait_did,
-                                &segments[segments.len()-2],
-                                segments.last().unwrap())
-                }
-                def::DefMod(id) => {
-                    tcx.sess.span_bug(span,
-                                      &format!("found module name used as a type: {}",
-                                               tcx.map.node_to_string(id.node)));
-                }
-                def::DefPrimTy(prim_ty) => {
-                    prim_ty_to_ty(tcx, span, segments, prim_ty)
-                }
-                _ => {
-                    span_fatal!(tcx.sess, span, E0248,
-                                "found value name used as a type: {:?}", base_def);
-                }
+            let (mut def, max_depth) = result;
+            let base_ty_end = path.segments.len() - max_depth;
+            let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
+                Some(ast_ty_to_ty(this, rscope, &*qpath.self_type))
+            } else {
+                None
             };
-
-            // If any associated type segments remain, attempt to resolve them.
-            let mut ty = base_ty;
-            let mut def = base_def;
-            for depth in (0..max_depth).rev() {
-                if ty.sty == ty::ty_err {
-                    break;
-                }
-                // This is pretty bad (it will fail except for T::A and Self::A).
-                let segment = &path.segments[path.segments.len()-depth-1];
-                let (a_ty, a_def) = associated_path_def_to_ty(this, span,
-                                                              ty, def, segment);
-                ty = a_ty;
-                def = a_def;
-            }
+            let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span,
+                                                PathParamMode::Explicit, &mut def,
+                                                opt_self_ty,
+                                                &path.segments[..base_ty_end],
+                                                &path.segments[base_ty_end..]);
 
             if max_depth != 0 && ty.sty != ty::ty_err {
                 // Write back the new resolution.
index 34c52981b794dff838208073f38a0d048a9cb59f..edbda795bde3c075e131b22ce282d56f4af1d201 100644 (file)
@@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     };
 
     instantiate_path(pcx.fcx,
-                     path,
+                     &path.segments,
                      ty::lookup_item_type(tcx, enum_def_id),
                      &ty::lookup_predicates(tcx, enum_def_id),
                      None,
@@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, &path.segments,
+                     path_scheme, &ctor_predicates,
+                     None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
index 256cd415a33afbf9a07ea87a8042cdd794e8f328..488d9d53dbe39978298d8e004f74d4d694d490d1 100644 (file)
@@ -14,6 +14,7 @@
 use check::{FnCtxt};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
+use middle::def;
 use middle::subst;
 use middle::traits;
 use middle::ty::*;
@@ -66,7 +67,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         call_expr_id: ast::NodeId)
                         -> bool
 {
-    match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
+    let mode = probe::Mode::MethodCall;
+    match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) {
         Ok(..) => true,
         Err(NoMatch(..)) => false,
         Err(Ambiguity(..)) => true,
@@ -103,8 +105,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
            call_expr.repr(fcx.tcx()),
            self_expr.repr(fcx.tcx()));
 
+    let mode = probe::Mode::MethodCall;
     let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
-    let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id));
+    let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id));
     Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
 }
 
@@ -301,6 +304,23 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Some(callee)
 }
 
+pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span,
+                              method_name: ast::Name,
+                              self_ty: Ty<'tcx>,
+                              expr_id: ast::NodeId)
+                              -> Result<def::Def, MethodError>
+{
+    let mode = probe::Mode::Path;
+    let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
+    let def_id = pick.method_ty.def_id;
+    let provenance = match pick.kind {
+        probe::InherentImplPick(impl_def_id) => def::FromImpl(impl_def_id),
+        _ => def::FromTrait(pick.method_ty.container.id())
+    };
+    Ok(def::DefMethod(def_id, provenance))
+}
+
 
 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
 /// index (or `None`, if no such method).
index 1cc4fe37fbdddf59928799b287752c412457d9db..938b7edeef2ff2b96d3b5074cd1a945317febd04 100644 (file)
@@ -37,6 +37,7 @@
 struct ProbeContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
+    mode: Mode,
     method_name: ast::Name,
     steps: Rc<Vec<CandidateStep<'tcx>>>,
     opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
@@ -108,17 +109,30 @@ pub enum PickAdjustment {
     AutoRef(ast::Mutability, Box<PickAdjustment>),
 }
 
+#[derive(PartialEq, Eq, Copy)]
+pub enum Mode {
+    // An expression of the form `receiver.method_name(...)`.
+    // Autoderefs are performed on `receiver`, lookup is done based on the
+    // `self` argument  of the method, and static methods aren't considered.
+    MethodCall,
+    // An expression of the form `Type::method` or `<T>::method`.
+    // No autoderefs are performed, lookup is done based on the type each
+    // implementation is for, and static methods are included.
+    Path
+}
+
 pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                        span: Span,
+                       mode: Mode,
                        method_name: ast::Name,
                        self_ty: Ty<'tcx>,
-                       call_expr_id: ast::NodeId)
+                       scope_expr_id: ast::NodeId)
                        -> PickResult<'tcx>
 {
-    debug!("probe(self_ty={}, method_name={}, call_expr_id={})",
+    debug!("probe(self_ty={}, method_name={}, scope_expr_id={})",
            self_ty.repr(fcx.tcx()),
            method_name,
-           call_expr_id);
+           scope_expr_id);
 
     // FIXME(#18741) -- right now, creating the steps involves evaluating the
     // `*` operator, which registers obligations that then escape into
@@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // it ride, although it's really not great, and in fact could I
     // think cause spurious errors. Really though this part should
     // take place in the `fcx.infcx().probe` below.
-    let steps = match create_steps(fcx, span, self_ty) {
-        Some(steps) => steps,
-        None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+    let steps = if mode == Mode::MethodCall {
+        match create_steps(fcx, span, self_ty) {
+            Some(steps) => steps,
+            None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+        }
+    } else {
+        vec![CandidateStep {
+            self_ty: self_ty,
+            adjustment: AutoDeref(0)
+        }]
     };
 
     // Create a list of simplified self types, if we can.
@@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // this creates one big transaction so that all type variables etc
     // that we create during the probe process are removed later
-    let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
     fcx.infcx().probe(|_| {
-        let (steps, opt_simplified_steps) = dummy.take().unwrap();
-        let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
+        let mut probe_cx = ProbeContext::new(fcx,
+                                             span,
+                                             mode,
+                                             method_name,
+                                             steps,
+                                             opt_simplified_steps);
         probe_cx.assemble_inherent_candidates();
-        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id));
+        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id));
         probe_cx.pick()
     })
 }
@@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn new(fcx: &'a FnCtxt<'a,'tcx>,
            span: Span,
+           mode: Mode,
            method_name: ast::Name,
            steps: Vec<CandidateStep<'tcx>>,
            opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
@@ -206,6 +231,7 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
         ProbeContext {
             fcx: fcx,
             span: span,
+            mode: mode,
             method_name: method_name,
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
@@ -292,11 +318,12 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
             return self.record_static_candidate(ImplSource(impl_def_id));
         }
 
-        let impl_substs = self.impl_substs(impl_def_id);
+        let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
+        let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
 
         // Determine the receiver type that the method itself expects.
         let xform_self_ty =
-            self.xform_self_ty(&method, &impl_substs);
+            self.xform_self_ty(&method, impl_ty, &impl_substs);
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
@@ -330,7 +357,9 @@ fn assemble_inherent_candidates_from_object(&mut self,
                                                           new_trait_ref.def_id,
                                                           method_num);
 
-            let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs);
+            let xform_self_ty = this.xform_self_ty(&m,
+                                                   new_trait_ref.self_ty(),
+                                                   new_trait_ref.substs);
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
@@ -373,7 +402,9 @@ fn assemble_inherent_candidates_from_param(&mut self,
                 this.erase_late_bound_regions(&poly_trait_ref);
 
             let xform_self_ty =
-                this.xform_self_ty(&m, trait_ref.substs);
+                this.xform_self_ty(&m,
+                                   trait_ref.self_ty(),
+                                   trait_ref.substs);
 
             debug!("found match: trait_ref={} substs={} m={}",
                    trait_ref.repr(this.tcx()),
@@ -540,7 +571,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
                 continue;
             }
 
-            let impl_substs = self.impl_substs(impl_def_id);
+            let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
 
             debug!("impl_substs={}", impl_substs.repr(self.tcx()));
 
@@ -553,7 +584,9 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
 
             // Determine the receiver type that the method itself expects.
             let xform_self_ty =
-                self.xform_self_ty(&method, impl_trait_ref.substs);
+                self.xform_self_ty(&method,
+                                   impl_trait_ref.self_ty(),
+                                   impl_trait_ref.substs);
 
             debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
 
@@ -630,7 +663,9 @@ fn assemble_closure_candidates(&mut self,
                                                              &trait_def.generics,
                                                              step.self_ty);
 
-            let xform_self_ty = self.xform_self_ty(&method_ty, &substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   step.self_ty,
+                                                   &substs);
             self.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 method_ty: method_ty.clone(),
@@ -684,7 +719,9 @@ fn assemble_projection_candidates(&mut self,
                        bound.repr(self.tcx()));
 
                 if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
-                    let xform_self_ty = self.xform_self_ty(&method, bound.substs);
+                    let xform_self_ty = self.xform_self_ty(&method,
+                                                           bound.self_ty(),
+                                                           bound.substs);
 
                     debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
                            bound.repr(self.tcx()),
@@ -714,7 +751,9 @@ fn assemble_where_clause_candidates(&mut self,
                           .filter(|b| b.def_id() == trait_def_id)
         {
             let bound = self.erase_late_bound_regions(&poly_bound);
-            let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   bound.self_ty(),
+                                                   bound.substs);
 
             debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
                    bound.repr(self.tcx()),
@@ -1023,7 +1062,9 @@ fn has_applicable_self(&self, method: &ty::Method) -> bool {
         // "fast track" -- check for usage of sugar
         match method.explicit_self {
             ty::StaticExplicitSelfCategory => {
-                // fallthrough
+                if self.mode == Mode::Path {
+                    return true;
+                }
             }
             ty::ByValueExplicitSelfCategory |
             ty::ByReferenceExplicitSelfCategory(..) |
@@ -1047,11 +1088,13 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
 
     fn xform_self_ty(&self,
                      method: &Rc<ty::Method<'tcx>>,
+                     impl_ty: Ty<'tcx>,
                      substs: &subst::Substs<'tcx>)
                      -> Ty<'tcx>
     {
-        debug!("xform_self_ty(self_ty={}, substs={})",
-               method.fty.sig.0.inputs[0].repr(self.tcx()),
+        debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
+               impl_ty.repr(self.tcx()),
+               method.fty.sig.0.inputs.get(0).repr(self.tcx()),
                substs.repr(self.tcx()));
 
         assert!(!substs.has_escaping_regions());
@@ -1063,6 +1106,11 @@ fn xform_self_ty(&self,
         // if there are any.
         assert_eq!(substs.types.len(subst::FnSpace), 0);
         assert_eq!(substs.regions().len(subst::FnSpace), 0);
+
+        if self.mode == Mode::Path {
+            return impl_ty;
+        }
+
         let placeholder;
         let mut substs = substs;
         if
@@ -1094,9 +1142,10 @@ fn xform_self_ty(&self,
         xform_self_ty
     }
 
-    fn impl_substs(&self,
-                   impl_def_id: ast::DefId)
-                   -> subst::Substs<'tcx>
+    /// Get the type of an impl and generate substitutions with placeholders.
+    fn impl_ty_and_substs(&self,
+                          impl_def_id: ast::DefId)
+                          -> (Ty<'tcx>, subst::Substs<'tcx>)
     {
         let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
 
@@ -1108,7 +1157,8 @@ fn impl_substs(&self,
             impl_pty.generics.regions.map(
                 |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static
 
-        subst::Substs::new(type_vars, region_placeholders)
+        let substs = subst::Substs::new(type_vars, region_placeholders);
+        (impl_pty.ty, substs)
     }
 
     /// Replace late-bound-regions bound by `value` with `'static` using
index 4daa9a5d80ab001599e96e60729ad4c51a9a2539..7a4fab5e56cf0253621490a0e77239a70243b46b 100644 (file)
 use self::IsBinopAssignment::*;
 use self::TupleArgumentsFlag::*;
 
-use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
+use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 use check::_match::pat_ctxt;
 use fmt_macros::{Parser, Piece, Position};
+use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
 use middle::{const_eval, def};
 use middle::infer;
 use middle::mem_categorization as mc;
@@ -1598,26 +1599,11 @@ fn instantiate_struct_literal_ty(&self,
         let ty::TypeScheme { generics, ty: decl_ty } =
             ty::lookup_item_type(tcx, did);
 
-        let wants_params =
-            generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
-
-        let needs_defaults =
-            wants_params &&
-            path.segments.iter().all(|s| s.parameters.is_empty());
-
-        let substs = if needs_defaults {
-            let tps =
-                self.infcx().next_ty_vars(generics.types.len(TypeSpace));
-            let rps =
-                self.infcx().region_vars_for_defs(path.span,
-                                                  generics.regions.get_slice(TypeSpace));
-            Substs::new_type(tps, rps)
-        } else {
-            astconv::ast_path_substs_for_ty(self, self,
-                                            path.span,
-                                            &generics,
-                                            path.segments.last().unwrap())
-        };
+        let substs = astconv::ast_path_substs_for_ty(self, self,
+                                                     path.span,
+                                                     PathParamMode::Optional,
+                                                     &generics,
+                                                     path.segments.last().unwrap());
 
         let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
 
@@ -3604,21 +3590,57 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref path) => {
-          let defn = lookup_def(fcx, path.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
+      ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => {
+          let opt_self_ty = if let ast::ExprQPath(ref qpath) = expr.node {
+              Some(fcx.to_ty(&*qpath.self_type))
+          } else {
+              None
+          };
 
-          // We always require that the type provided as the value for
-          // a type parameter outlives the moment of instantiation.
-          constrain_path_type_parameters(fcx, expr);
-      }
-      ast::ExprQPath(ref qpath) => {
-          let self_ty = fcx.to_ty(&*qpath.self_type);
-          let defn = lookup_def(fcx, expr.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, &qpath.path, scheme, &predicates, Some(self_ty),
-                           defn, expr.span, expr.id);
+          // Helpers to avoid keeping the RefCell borrow for too long.
+          let get_def = |&:| tcx.def_map.borrow().get(&id).cloned();
+          let get_partial_def = |&:| tcx.partial_def_map.borrow().get(&id).cloned();
+
+          if let Some(def) = get_def() {
+              let (scheme, predicates) =
+                  type_scheme_and_predicates_for_def(fcx, expr.span, def);
+              instantiate_path(fcx, &path.segments,
+                               scheme, &predicates,
+                               None, def, expr.span, id);
+          } else if let Some(partial) = get_partial_def() {
+              let mut def = partial.base_type;
+              let ty_segments = path.segments.init();
+              let ty_assoc_num = partial.extra_associated_types as usize;
+              let base_ty_end = ty_segments.len() - ty_assoc_num;
+              let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
+                                                           PathParamMode::Optional,
+                                                           &mut def,
+                                                           opt_self_ty,
+                                                           &ty_segments[..base_ty_end],
+                                                           &ty_segments[base_ty_end..]);
+              let method_segment = path.segments.last().unwrap();
+              let method_name = method_segment.identifier.name;
+              match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
+                  Ok(def) => {
+                      // Write back the new resolution.
+                      tcx.def_map.borrow_mut().insert(id, def);
+
+                      let (scheme, predicates) =
+                          type_scheme_and_predicates_for_def(fcx, expr.span, def);
+                      instantiate_path(fcx, slice::ref_slice(method_segment),
+                                       scheme, &predicates,
+                                       Some(ty), def, expr.span, id);
+                  }
+                  Err(error) => {
+                      method::report_error(fcx, expr.span, ty,
+                                           method_name, expr, error);
+                      fcx.write_error(id);
+                  }
+              }
+          } else {
+              tcx.sess.span_bug(expr.span,
+                                &format!("unbound path {}", expr.repr(tcx))[])
+          }
 
           // We always require that the type provided as the value for
           // a type parameter outlives the moment of instantiation.
@@ -4641,7 +4663,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefForeignMod(..) |
         def::DefUse(..) |
         def::DefRegion(..) |
-        def::DefTyParamBinder(..) |
         def::DefLabel(..) |
         def::DefSelfTy(..) => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
@@ -4652,15 +4673,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  path: &ast::Path,
+                                  segments: &[ast::PathSegment],
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
-    debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
-           path.repr(fcx.tcx()),
+    debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
+           segments,
            def.repr(fcx.tcx()),
            node_id,
            type_scheme.repr(fcx.tcx()));
@@ -4724,7 +4745,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     //
     // The first step then is to categorize the segments appropriately.
 
-    assert!(path.segments.len() >= 1);
+    assert!(segments.len() >= 1);
+
+    // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory.
+    let mut require_type_space = opt_self_ty.is_some();
+
     let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
@@ -4738,7 +4763,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefTyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::TypeSpace));
         }
 
@@ -4746,14 +4771,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefFn(..) |
         def::DefConst(..) |
         def::DefStatic(..) => {
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::FnSpace));
         }
 
         // Case 3. Reference to a method.
         def::DefMethod(_, providence) => {
-            assert!(path.segments.len() >= 2);
-
             match providence {
                 def::FromTrait(trait_did) => {
                     callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
@@ -4761,9 +4784,16 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 def::FromImpl(_) => {}
             }
 
-            segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
-            segment_spaces.push(Some(subst::TypeSpace));
-            segment_spaces.push(Some(subst::FnSpace));
+            if segments.len() >= 2 {
+                segment_spaces = repeat(None).take(segments.len() - 2).collect();
+                segment_spaces.push(Some(subst::TypeSpace));
+                segment_spaces.push(Some(subst::FnSpace));
+            } else {
+                // `<T>::method` will end up here, and so can `T::method`.
+                assert!(opt_self_ty.is_some());
+                require_type_space = false;
+                segment_spaces = vec![Some(subst::FnSpace)];
+            }
         }
 
         // Other cases. Various nonsense that really shouldn't show up
@@ -4776,10 +4806,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefUpvar(..) => {
-            segment_spaces = repeat(None).take(path.segments.len()).collect();
+            segment_spaces = repeat(None).take(segments.len()).collect();
         }
     }
-    assert_eq!(segment_spaces.len(), path.segments.len());
+    assert_eq!(segment_spaces.len(), segments.len());
 
     debug!("segment_spaces={:?}", segment_spaces);
 
@@ -4793,16 +4823,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // provided (if any) into their appropriate spaces. We'll also report
     // errors if type parameters are provided in an inappropriate place.
     let mut substs = Substs::empty();
-    for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
+    for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
         match *opt_space {
             None => {
-                report_error_if_segment_contains_type_parameters(fcx, segment);
+                check_path_args(fcx.tcx(), slice::ref_slice(segment),
+                                NO_TPS | NO_REGIONS);
             }
 
             Some(space) => {
                 push_explicit_parameters_from_segment_to_substs(fcx,
                                                                 space,
-                                                                path.span,
+                                                                span,
                                                                 type_defs,
                                                                 region_defs,
                                                                 segment,
@@ -4824,7 +4855,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // a problem.
     for &space in &ParamSpace::all() {
         adjust_type_parameters(fcx, span, space, type_defs,
-                               opt_self_ty.is_some(), &mut substs);
+                               require_type_space, &mut substs);
         assert_eq!(substs.types.len(space), type_defs.len(space));
 
         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
@@ -4851,23 +4882,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
     return;
 
-    fn report_error_if_segment_contains_type_parameters(
-        fcx: &FnCtxt,
-        segment: &ast::PathSegment)
-    {
-        for typ in &segment.parameters.types() {
-            span_err!(fcx.tcx().sess, typ.span, E0085,
-                "type parameters may not appear here");
-            break;
-        }
-
-        for lifetime in &segment.parameters.lifetimes() {
-            span_err!(fcx.tcx().sess, lifetime.span, E0086,
-                "lifetime parameters may not appear here");
-            break;
-        }
-    }
-
     /// Finds the parameters that the user provided and adds them to `substs`. If too many
     /// parameters are provided, then reports an error and clears the output vector.
     ///
index 46e1f6f076a7bbd028aabeb3f29c80dbb2e24e2d..976c794735fbb177244f03ceb783ae59fcc7d605 100644 (file)
@@ -1684,8 +1684,8 @@ fn is_param(ccx: &CollectCtxt,
                 -> bool
     {
         match ast_ty.node {
-            ast::TyPath(_, id) => {
-                match ccx.tcx.def_map.borrow()[id] {
+            ast::TyPath(_) => {
+                match ccx.tcx.def_map.borrow()[ast_ty.id] {
                     def::DefTyParam(s, i, _, _) => {
                         space == s && index == i
                     }
index e4f7521c33303cc340faabfacff70c593b767580..2652fb5dfc2fd6dc453f73f1d3d9094847ccbe86 100644 (file)
@@ -30,7 +30,5 @@ fn to_string(&self) -> String {
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR unresolved name `Point::new`
-    //~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
     println!("{}", p.to_string());
 }
index dce12030f79427caa502bb9f6c8cfc072ede4c76..23d90c5ee292bf288f0c6b8c64ada2ff4f117264 100644 (file)
@@ -77,18 +77,27 @@ macro_rules! tests {
     //    , (vec![b'f', b'o', b'o'], u8_as_i8);
 
     // Trait static methods.
+    bool::size, fn() -> uint, ();
     <bool as Size>::size, fn() -> uint, ();
+
     Default::default, fn() -> int, ();
+    int::default, fn() -> int, ();
     <int as Default>::default, fn() -> int, ();
+
     Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    int::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
     <int as Rand>::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
     Rand::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    int::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
     <int as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
 
     // Trait non-static methods.
     Clone::clone, fn(&int) -> int, (&5);
+    int::clone, fn(&int) -> int, (&5);
     <int as Clone>::clone, fn(&int) -> int, (&5);
+
     FromIterator::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
+    Vec::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
     <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
         (Some(5).into_iter());
     <Vec<int> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
@@ -97,9 +106,14 @@ macro_rules! tests {
         (Some(5).into_iter());
     <Vec<int> as FromIterator<_>>::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
         (Some(5).into_iter());
+
     Add::add, fn(i32, i32) -> i32, (5, 6);
+    i32::add, fn(i32, i32) -> i32, (5, 6);
     <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
     <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
+
+    String::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
     <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
         ("foo".to_string());
     <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,