Skip to content

Commit fc5fe7f

Browse files
committed
Use partial path resolutions in expressions for UFCS desugaring.
1 parent ebdaa8e commit fc5fe7f

File tree

9 files changed

+377
-206
lines changed

9 files changed

+377
-206
lines changed

src/librustc/middle/astconv_util.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,36 @@
1717
use middle::def;
1818
use middle::ty::{self, Ty};
1919
use syntax::ast;
20-
use syntax::codemap::Span;
2120
use util::ppaux::Repr;
2221

2322
pub const NO_REGIONS: uint = 1;
2423
pub const NO_TPS: uint = 2;
2524

26-
pub fn check_path_args(tcx: &ty::ctxt,
27-
span: Span,
28-
segments: &[ast::PathSegment],
29-
flags: uint) {
30-
if (flags & NO_TPS) != 0 {
31-
if segments.iter().any(|s| s.parameters.has_types()) {
32-
span_err!(tcx.sess, span, E0109,
33-
"type parameters are not allowed on this type");
25+
pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
26+
for segment in segments {
27+
if (flags & NO_TPS) != 0 {
28+
for typ in segment.parameters.types() {
29+
span_err!(tcx.sess, typ.span, E0109,
30+
"type parameters are not allowed on this type");
31+
break;
32+
}
3433
}
35-
}
3634

37-
if (flags & NO_REGIONS) != 0 {
38-
if segments.iter().any(|s| s.parameters.has_lifetimes()) {
39-
span_err!(tcx.sess, span, E0110,
40-
"lifetime parameters are not allowed on this type");
35+
if (flags & NO_REGIONS) != 0 {
36+
for lifetime in segment.parameters.lifetimes() {
37+
span_err!(tcx.sess, lifetime.span, E0110,
38+
"lifetime parameters are not allowed on this type");
39+
break;
40+
}
4141
}
4242
}
4343
}
4444

4545
pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
46-
span: Span,
4746
segments: &[ast::PathSegment],
4847
nty: ast::PrimTy)
4948
-> Ty<'tcx> {
50-
check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
49+
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
5150
match nty {
5251
ast::TyBool => tcx.types.bool,
5352
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)
6968
Some(&d) => d
7069
};
7170
if let def::DefPrimTy(nty) = def {
72-
Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty))
71+
Some(prim_ty_to_ty(tcx, &path.segments[], nty))
7372
} else {
7473
None
7574
}

src/librustc_resolve/lib.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4055,16 +4055,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
40554055
// multiple elements in it or not.
40564056

40574057
ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
4058-
if let ExprQPath(_) = expr.node {
4058+
let max_assoc_types = if let ExprQPath(_) = expr.node {
40594059
// Make sure the trait is valid.
40604060
let _ = self.resolve_trait_reference(expr.id, path, 1);
4061+
1
4062+
} else {
4063+
path.segments.len()
4064+
};
4065+
4066+
let mut result = self.with_no_errors(|this| {
4067+
this.resolve_path(expr.id, path, 0, ValueNS, true)
4068+
});
4069+
for depth in 1..max_assoc_types {
4070+
if result.is_some() {
4071+
break;
4072+
}
4073+
self.with_no_errors(|this| {
4074+
result = this.resolve_path(expr.id, path, depth, TypeNS, true);
4075+
});
4076+
}
4077+
if let Some((DefMod(_), _, _)) = result {
4078+
// A module is not a valid type or value.
4079+
result = None;
40614080
}
40624081

40634082
// This is a local path in the value namespace. Walk through
40644083
// scopes looking for it.
4065-
match self.resolve_path(expr.id, path, 0, ValueNS, true) {
4084+
match result {
40664085
// Check if struct variant
4067-
Some((DefVariant(_, _, true), _, _)) => {
4086+
Some((DefVariant(_, _, true), _, 0)) => {
40684087
let path_name = self.path_names_to_string(path, 0);
40694088
self.resolve_error(expr.span,
40704089
&format!("`{}` is a struct variant name, but \
@@ -4082,6 +4101,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
40824101
debug!("(resolving expr) resolved `{}`",
40834102
self.path_names_to_string(path, 0));
40844103

4104+
// Partial resolutions will need the set of traits in scope,
4105+
// so they can be completed during typeck.
4106+
if def.2 != 0 {
4107+
let method_name = path.segments.last().unwrap().identifier.name;
4108+
let traits = self.search_for_traits_containing_method(method_name);
4109+
self.trait_map.insert(expr.id, traits);
4110+
}
4111+
40854112
self.record_def(expr.id, def);
40864113
}
40874114
None => {
@@ -4107,6 +4134,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
41074134

41084135
}
41094136
_ => {
4137+
// Keep reporting some errors even if they're ignored above.
4138+
self.resolve_path(expr.id, path, 0, ValueNS, true);
4139+
41104140
let mut method_scope = false;
41114141
self.value_ribs.iter().rev().all(|rib| {
41124142
method_scope = match rib.kind {

0 commit comments

Comments
 (0)