Skip to content

Commit

Permalink
rustc: implement fully qualified UFCS expressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jan 15, 2015
1 parent 75d7f82 commit b90028d
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 38 deletions.
53 changes: 28 additions & 25 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use rustc::util::lev_distance::lev_distance;
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprStruct, FnDecl};
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
Expand Down Expand Up @@ -3169,7 +3169,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitImplementation => "implement",
TraitDerivation => "derive",
TraitObject => "reference",
TraitQPath => "extract an associated type from",
TraitQPath => "extract an associated item from",
};

let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
Expand Down Expand Up @@ -3565,31 +3565,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}

match result_def {
None => {
match self.resolve_path(ty.id, path, TypeNS, true) {
Some(def) => {
debug!("(resolving type) resolved `{:?}` to \
type {:?}",
token::get_ident(path.segments.last().unwrap() .identifier),
def);
result_def = Some(def);
}
None => {
result_def = None;
}
}
}
Some(_) => {} // Continue.
if let None = result_def {
result_def = self.resolve_path(ty.id, path, TypeNS, true);
}

match result_def {
Some(def) => {
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` \
(id {})",
(id {}) = {:?}",
self.path_names_to_string(path),
path_id);
path_id, def);
self.record_def(path_id, def);
}
None => {
Expand All @@ -3609,6 +3595,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TyQPath(ref qpath) => {
self.resolve_type(&*qpath.self_type);
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
for ty in qpath.item_path.parameters.types().into_iter() {
self.resolve_type(&**ty);
}
for binding in qpath.item_path.parameters.bindings().into_iter() {
self.resolve_type(&*binding.ty);
}
}

TyPolyTraitRef(ref bounds) => {
Expand Down Expand Up @@ -4400,15 +4392,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// The interpretation of paths depends on whether the path has
// multiple elements in it or not.

ExprPath(ref path) => {
ExprPath(_) | ExprQPath(_) => {
let mut path_from_qpath;
let path = match expr.node {
ExprPath(ref path) => path,
ExprQPath(ref qpath) => {
self.resolve_type(&*qpath.self_type);
self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
path_from_qpath = qpath.trait_ref.path.clone();
path_from_qpath.segments.push(qpath.item_path.clone());
&path_from_qpath
}
_ => unreachable!()
};
// This is a local path in the value namespace. Walk through
// scopes looking for it.

let path_name = self.path_names_to_string(path);

match self.resolve_path(expr.id, path, ValueNS, true) {
// Check if struct variant
Some((DefVariant(_, _, true), _)) => {
let path_name = self.path_names_to_string(path);
self.resolve_error(expr.span,
format!("`{}` is a struct variant name, but \
this expression \
Expand All @@ -4423,7 +4425,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(def) => {
// Write the result into the def map.
debug!("(resolving expr) resolved `{}`",
path_name);
self.path_names_to_string(path));

self.record_def(expr.id, def);
}
Expand All @@ -4432,6 +4434,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and enum-like
// structs, which wouldn't result in this error.)
let path_name = self.path_names_to_string(path);
match self.with_no_errors(|this|
this.resolve_path(expr.id, path, TypeNS, false)) {
Some((DefTy(struct_id, _), _))
Expand Down
16 changes: 11 additions & 5 deletions src/librustc_trans/save/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
span: Span,
path: &ast::Path,
ref_kind: Option<recorder::Row>) {
if generated_code(path.span) {
if generated_code(span) {
return
}

Expand Down Expand Up @@ -1307,9 +1307,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
visit::walk_expr(self, ex);
},
ast::ExprPath(ref path) => {
self.process_path(ex.id, ex.span, path, None);
self.process_path(ex.id, path.span, path, None);
visit::walk_path(self, path);
}
ast::ExprQPath(ref qpath) => {
let mut path = qpath.trait_ref.path.clone();
path.segments.push(qpath.item_path.clone());
self.process_path(ex.id, ex.span, &path, None);
visit::walk_qpath(self, ex.span, &**qpath);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
Expand Down Expand Up @@ -1439,7 +1445,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
"")
}
def::DefVariant(..) => {
paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
paths_to_process.push((id, p.clone(), Some(ref_kind)))
}
// FIXME(nrc) what are these doing here?
def::DefStatic(_, _) => {}
Expand All @@ -1448,8 +1454,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
*def)
}
}
for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
self.process_path(id, span, path, ref_kind);
for &(id, ref path, ref_kind) in paths_to_process.iter() {
self.process_path(id, path.span, path, ref_kind);
}
self.collecting = false;
self.collected_paths.clear();
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
};

instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),
def, pat.span, pat.id);
None, def, pat.span, pat.id);

let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);
Expand Down Expand Up @@ -505,7 +505,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
} else {
ctor_scheme
};
instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id);
instantiate_path(pcx.fcx, path, path_scheme, None, def, pat.span, pat.id);

let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);
Expand Down
27 changes: 24 additions & 3 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3553,10 +3553,25 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
};
fcx.write_ty(id, oprnd_t);
}
ast::ExprPath(ref pth) => {
let defn = lookup_def(fcx, pth.span, id);
ast::ExprPath(ref path) => {
let defn = lookup_def(fcx, path.span, id);
let pty = type_scheme_for_def(fcx, expr.span, defn);
instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);

// 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) => {
// Require explicit type params for the trait.
let self_ty = fcx.to_ty(&*qpath.self_type);
astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);

let defn = lookup_def(fcx, expr.span, id);
let pty = type_scheme_for_def(fcx, expr.span, defn);
let mut path = qpath.trait_ref.path.clone();
path.segments.push(qpath.item_path.clone());
instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);

// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
Expand Down Expand Up @@ -4619,6 +4634,7 @@ pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
path: &ast::Path,
type_scheme: TypeScheme<'tcx>,
opt_self_ty: Option<Ty<'tcx>>,
def: def::Def,
span: Span,
node_id: ast::NodeId) {
Expand Down Expand Up @@ -4776,6 +4792,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
}
if let Some(self_ty) = opt_self_ty {
// `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
assert_eq!(type_defs.len(subst::SelfSpace), 1);
substs.types.push(subst::SelfSpace, self_ty);
}

// Now we have to compare the types that the user *actually*
// provided against the types that were *expected*. If the user
Expand Down
17 changes: 17 additions & 0 deletions src/test/compile-fail/ufcs-qpath-missing-params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::IntoCow;

fn main() {
<String as IntoCow>::into_cow("foo".to_string());
//~^ ERROR wrong number of type arguments: expected 2, found 0
}

21 changes: 21 additions & 0 deletions src/test/compile-fail/ufcs-qpath-self-mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ops::Add;

fn main() {
<i32 as Add<u32>>::add(1, 2);
//~^ ERROR the trait `core::ops::Add<u32>` is not implemented for the type `i32`
<i32 as Add<i32>>::add(1u32, 2);
//~^ ERROR mismatched types
<i32 as Add<i32>>::add(1, 2u32);
//~^ ERROR mismatched types
}

30 changes: 27 additions & 3 deletions src/test/run-pass/const-polymorphic-paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

#![feature(macro_rules)]

use std::borrow::{Cow, IntoCow};
use std::collections::Bitv;
use std::default::Default;
use std::iter::FromIterator;
use std::ops::Add;
use std::option::IntoIter as OptionIter;
use std::rand::Rand;
use std::rand::XorShiftRng as DummyRng;
Expand All @@ -28,6 +30,11 @@ fn u8_as_i8(x: u8) -> i8 { x as i8 }
fn odd(x: uint) -> bool { x % 2 == 1 }
fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }

trait Size: Sized {
fn size() -> uint { std::mem::size_of::<Self>() }
}
impl<T> Size for T {}

macro_rules! tests {
($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
const C: $ty = $expr;
Expand Down Expand Up @@ -70,14 +77,31 @@ tests! {
// , (vec![b'f', b'o', b'o'], u8_as_i8);

// Trait static methods.
// FIXME qualified path expressions aka UFCS i.e. <T as Trait>::method.
<bool as Size>::size, fn() -> uint, ();
Default::default, fn() -> int, ();
<int as Default>::default, fn() -> int, ();
Rand::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 as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());

// Trait non-static methods.
Clone::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());
FromIterator::from_iter::<OptionIter<int>>, 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>,
(Some(5).into_iter());
FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
(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 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
<i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
<String as IntoCow<_, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
("foo".to_string());
<String as IntoCow<'static, _, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
("foo".to_string());
}

9 comments on commit b90028d

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at eddyb@b90028d

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging 44 batched pull requests into batch

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status: {"merge_sha": "56ee93164890302d6ffad7c1be1c125f955a45d4", "rollup_pulls": [[21077, "b90028d77092e30fb89b416ac06c847e1fce359a"], [20463, "9f5fc563d3d592d5e44ab71759ffa26d326b3daa"], [20632, "4b14f67df3c28cd1cd8ea5bf794a3e542c663d8d"], [20892, "9302dc5d9e13f716a21a5d9ebdcddc149a864b19"], [20929, "eabf2082856668c75ed6f7c229b24fb7755440bc"], [20964, "78b7e13bf02e59ad05a9d15725e3c36e9dcf7187"], [20976, "415fc5f0f10b6180193ecd309b21ae80a1efa6a9"], [20985, "11737a3e1d5080c10f1ca366a12cf8fed7941d49"], [20986, "a3d87fa448de23d9d2faaf6f68803e5925653244"], [20988, "8eba032f52a0b16b39a94267b4884f361e022c36"], [21001, "e1ff480e433697ae546e2cedebf659dc1b19572f"], [21005, "933303413e4fe97dbfd7e7f0a6f26dfb077696e8"], [21011, "ba9e223c57de82fbdb4da1446de570e028477aec"], [21013, "c403794310814d2d83e80f2f10308195505b48be"], [21014, "285277dd804e8e380dde764a00c97a721b4ef976"], [21015, "be407180d726f0121ccce9a7439f14de1731435c"], [21020, "e485d297ea6e882725c3d5b510183a3f8d816530"], [21023, "95f9e309f7307ace9218307f943f29662e21a1e5"], [21028, "425f449fdacb72f98a3e7c4326997b09b9b9a127"], [21029, "b704983ee925dff219ecc5b8e7dd2ba9fec64c1f"], [21031, "db7de969cfb50587475185e25bd09b7e73cafe83"], [21036, "d6e67e938bfce049432b3084787c055911b76f5c"], [21038, "2297b0cb0028965a2ef1d6a5de3d4c2dbe172825"], [21040, "16a8c4d2382d72aa414d89192422187acd290270"], [21041, "d7999d4041875ad4e9d16f400342301ee2eab081"], [21046, "599232503a7959faafa21bc8b38ca98f4b28e536"], [21054, "71884601f955c67b055fad8351074eae4f849769"], [21059, "6a7f0a99d8005187736c3c26c5cc2d538a42590f"], [21066, "323abc0eb0e99d445a38aa4fc0da93f5791ff492"], [21071, "9af8a646a964985fe42a91ea34672266c91ae295"], [21075, "31ac1fb93df9b9a2db332f055052dbfb779bdf91"], [21103, "1217007c8335ec2b3097583ff3e0ad15a35af26e"], [21105, "07f723f19bdf1054d140fc713f72f04a2f1b4258"], [21109, "ad0ce88c6cceec7a5cc3efc91b9447b05fd578a1"], [21110, "806c13589a319292849443d4b8ad44d2edc78cbf"], [21120, "6cfbcca41e259ddf93fb86a54e8d5f5bbcd3e6f1"], [21124, "40219249cf87585023e0d1b44de261dd56752142"], [21126, "fb556288737ececbc12b177b45a0717ff4dd5b66"], [21133, "5a16ceb291fd1b021efc342e3058c0f1ce534778"], [21141, "428da78de10310744a33b5e5b7d85e1a11e8e7ed"], [21148, "bf899e997e8aa3bf806f7cf0cf2a5e714ff705cc"], [21172, "e5ad89d176004931d7ffbf87e7c23bc71fc7418a"]]}

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing rollup candidate = 56ee931

Successful merges:

Failed merges:

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at eddyb@b90028d

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging 43 batched pull requests into batch

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status: {"merge_sha": "5eb2f591b22cc9f7858ec8cdc7cefe715789d91a", "rollup_pulls": [[21077, "b90028d77092e30fb89b416ac06c847e1fce359a"], [20463, "9f5fc563d3d592d5e44ab71759ffa26d326b3daa"], [20632, "4b14f67df3c28cd1cd8ea5bf794a3e542c663d8d"], [20892, "9302dc5d9e13f716a21a5d9ebdcddc149a864b19"], [20929, "eabf2082856668c75ed6f7c229b24fb7755440bc"], [20964, "78b7e13bf02e59ad05a9d15725e3c36e9dcf7187"], [20976, "415fc5f0f10b6180193ecd309b21ae80a1efa6a9"], [20985, "11737a3e1d5080c10f1ca366a12cf8fed7941d49"], [20986, "a3d87fa448de23d9d2faaf6f68803e5925653244"], [20988, "8eba032f52a0b16b39a94267b4884f361e022c36"], [21001, "e1ff480e433697ae546e2cedebf659dc1b19572f"], [21005, "933303413e4fe97dbfd7e7f0a6f26dfb077696e8"], [21011, "ba9e223c57de82fbdb4da1446de570e028477aec"], [21013, "c403794310814d2d83e80f2f10308195505b48be"], [21014, "285277dd804e8e380dde764a00c97a721b4ef976"], [21015, "be407180d726f0121ccce9a7439f14de1731435c"], [21020, "e485d297ea6e882725c3d5b510183a3f8d816530"], [21023, "95f9e309f7307ace9218307f943f29662e21a1e5"], [21028, "425f449fdacb72f98a3e7c4326997b09b9b9a127"], [21029, "b704983ee925dff219ecc5b8e7dd2ba9fec64c1f"], [21031, "db7de969cfb50587475185e25bd09b7e73cafe83"], [21036, "d6e67e938bfce049432b3084787c055911b76f5c"], [21038, "2297b0cb0028965a2ef1d6a5de3d4c2dbe172825"], [21040, "16a8c4d2382d72aa414d89192422187acd290270"], [21041, "d7999d4041875ad4e9d16f400342301ee2eab081"], [21046, "599232503a7959faafa21bc8b38ca98f4b28e536"], [21054, "71884601f955c67b055fad8351074eae4f849769"], [21059, "6a7f0a99d8005187736c3c26c5cc2d538a42590f"], [21066, "323abc0eb0e99d445a38aa4fc0da93f5791ff492"], [21071, "9af8a646a964985fe42a91ea34672266c91ae295"], [21075, "31ac1fb93df9b9a2db332f055052dbfb779bdf91"], [21103, "1217007c8335ec2b3097583ff3e0ad15a35af26e"], [21105, "07f723f19bdf1054d140fc713f72f04a2f1b4258"], [21109, "ad0ce88c6cceec7a5cc3efc91b9447b05fd578a1"], [21110, "806c13589a319292849443d4b8ad44d2edc78cbf"], [21120, "6cfbcca41e259ddf93fb86a54e8d5f5bbcd3e6f1"], [21124, "40219249cf87585023e0d1b44de261dd56752142"], [21126, "fb556288737ececbc12b177b45a0717ff4dd5b66"], [21133, "5a16ceb291fd1b021efc342e3058c0f1ce534778"], [21141, "428da78de10310744a33b5e5b7d85e1a11e8e7ed"], [21148, "bf899e997e8aa3bf806f7cf0cf2a5e714ff705cc"], [21172, "e5ad89d176004931d7ffbf87e7c23bc71fc7418a"]]}

@bors
Copy link
Contributor

@bors bors commented on b90028d Jan 15, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing rollup candidate = 5eb2f59

Successful merges:

Failed merges:

Please sign in to comment.