From 522d4b0a354b60b1b69d15773197c4c3dba521a5 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 13 Sep 2015 14:14:04 -0600 Subject: [PATCH 1/4] Fixed regression in associated item resolution with default type parameters that reference Self in traits. --- src/librustc_typeck/astconv.rs | 13 ++++++++- src/test/compile-fail/issue-28344.rs | 21 ++++++++++++++ .../unspecified-self-in-trait-ref.rs | 28 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-28344.rs create mode 100644 src/test/compile-fail/unspecified-self-in-trait-ref.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6f2d8345142be..b5b5113c4870d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -413,9 +413,20 @@ fn create_substs_for_ast_path<'tcx>( 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)) + .map(|p| { + 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 this.ty_infer(None, Some(&mut substs), Some(TypeSpace), span); + } + } + + this.ty_infer(Some(p.clone()), Some(&mut substs), Some(TypeSpace), span) + }) .collect() } else { types_provided 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..5ec9cf430f1d1 --- /dev/null +++ b/src/test/compile-fail/unspecified-self-in-trait-ref.rs @@ -0,0 +1,28 @@ +// 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 +} From af3a0b08055f9dac932264253040c3626a7052f6 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 13 Sep 2015 21:22:30 -0600 Subject: [PATCH 2/4] Refactor ty_infer invocation --- src/librustc_typeck/astconv.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b5b5113c4870d..13476ddebc17f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -412,21 +412,26 @@ fn create_substs_for_ast_path<'tcx>( // they were optional (e.g. paths inside expressions). let mut type_substs = if param_mode == PathParamMode::Optional && types_provided.is_empty() { + 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()) + } + let mut substs = region_substs.clone(); ty_param_defs .iter() - .map(|p| { - 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 this.ty_infer(None, Some(&mut substs), Some(TypeSpace), span); - } - } - - this.ty_infer(Some(p.clone()), Some(&mut substs), Some(TypeSpace), span) - }) + .map(|p| this.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs), + Some(TypeSpace), span)) .collect() } else { types_provided From 3d0774f5989fc9425c5dc0ab5118fdcabba33555 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 13 Sep 2015 21:43:24 -0600 Subject: [PATCH 3/4] Added test for partially supplied type params in which remaining reference non-existant self --- src/test/compile-fail/unspecified-self-in-trait-ref.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/compile-fail/unspecified-self-in-trait-ref.rs b/src/test/compile-fail/unspecified-self-in-trait-ref.rs index 5ec9cf430f1d1..2c2f113a7790c 100644 --- a/src/test/compile-fail/unspecified-self-in-trait-ref.rs +++ b/src/test/compile-fail/unspecified-self-in-trait-ref.rs @@ -25,4 +25,6 @@ fn main() { //~^ ERROR no associated item named let d = Bar::::lol(); //~^ ERROR no associated item named + let e = Bar::::lol(); + //~^ ERROR must be explicitly specified } From 4fec679399ddaf67d15adddad2677731f94dfa36 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 14 Sep 2015 02:33:29 -0600 Subject: [PATCH 4/4] Cleaner abstraction for type_substs --- src/librustc_typeck/astconv.rs | 71 ++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 13476ddebc17f..0537b176aef33 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -408,34 +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() { - 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()) - } - - let mut substs = region_substs.clone(); - - 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 - }; + 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, @@ -499,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>,