diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6f2d8345142be..0537b176aef33 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -408,18 +408,13 @@ fn create_substs_for_ast_path<'tcx>( .take_while(|x| x.default.is_none()) .count(); - // 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() { - let mut substs = region_substs.clone(); - ty_param_defs - .iter() - .map(|p| this.ty_infer(Some(p.clone()), Some(&mut substs), Some(TypeSpace), span)) - .collect() - } else { - types_provided - }; + let mut type_substs = get_type_substs_for_defs(this, + span, + types_provided, + param_mode, + ty_param_defs, + region_substs.clone(), + self_ty); let supplied_ty_param_count = type_substs.len(); check_type_argument_count(this.tcx(), span, supplied_ty_param_count, @@ -483,6 +478,42 @@ fn create_substs_for_ast_path<'tcx>( substs } +/// Returns types_provided if it is not empty, otherwise populating the +/// type parameters with inference variables as appropriate. +fn get_type_substs_for_defs<'tcx>(this: &AstConv<'tcx>, + span: Span, + types_provided: Vec>, + param_mode: PathParamMode, + ty_param_defs: &[ty::TypeParameterDef<'tcx>], + mut substs: Substs<'tcx>, + self_ty: Option>) + -> Vec> +{ + fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option>) + -> Option> + { + if let Some(ref default) = p.default { + if self_ty.is_none() && default.has_self_ty() { + // There is no suitable inference default for a type parameter + // that references self with no self-type provided. + return None; + } + } + + Some(p.clone()) + } + + if param_mode == PathParamMode::Optional && types_provided.is_empty() { + ty_param_defs + .iter() + .map(|p| this.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs), + Some(TypeSpace), span)) + .collect() + } else { + types_provided + } +} + struct ConvertedBinding<'tcx> { item_name: ast::Name, ty: Ty<'tcx>, diff --git a/src/test/compile-fail/issue-28344.rs b/src/test/compile-fail/issue-28344.rs new file mode 100644 index 0000000000000..751a42826d271 --- /dev/null +++ b/src/test/compile-fail/issue-28344.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::BitXor; + +fn main() { + let x: u8 = BitXor::bitor(0 as u8, 0 as u8); + //~^ ERROR must be specified + //~| no associated item named + + let g = BitXor::bitor; + //~^ ERROR must be specified + //~| no associated item named +} \ No newline at end of file diff --git a/src/test/compile-fail/unspecified-self-in-trait-ref.rs b/src/test/compile-fail/unspecified-self-in-trait-ref.rs new file mode 100644 index 0000000000000..2c2f113a7790c --- /dev/null +++ b/src/test/compile-fail/unspecified-self-in-trait-ref.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo { + fn foo(); +} + +pub trait Bar { + fn foo(); +} + +fn main() { + let a = Foo::lol(); + //~^ ERROR no associated item named + let b = Foo::<_>::lol(); + //~^ ERROR no associated item named + let c = Bar::lol(); + //~^ ERROR no associated item named + let d = Bar::::lol(); + //~^ ERROR no associated item named + let e = Bar::::lol(); + //~^ ERROR must be explicitly specified +}