Skip to content

Commit fe4f9b8

Browse files
committed
Use partial path resolutions in expressions for UFCS desugaring.
1 parent 7a3054f commit fe4f9b8

File tree

10 files changed

+387
-213
lines changed

10 files changed

+387
-213
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: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,7 +3018,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30183018
}
30193019

30203020
fn resolve_generics(&mut self, generics: &Generics) {
3021-
for type_parameter in &generics.ty_params {
3021+
for type_parameter in &*generics.ty_params {
30223022
self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
30233023
}
30243024
for predicate in &generics.where_clause.predicates {
@@ -4083,16 +4083,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
40834083
// multiple elements in it or not.
40844084

40854085
ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
4086-
if let ExprQPath(_) = expr.node {
4086+
let max_assoc_types = if let ExprQPath(_) = expr.node {
40874087
// Make sure the trait is valid.
40884088
let _ = self.resolve_trait_reference(expr.id, path, 1);
4089+
1
4090+
} else {
4091+
path.segments.len()
4092+
};
4093+
4094+
let mut result = self.with_no_errors(|this| {
4095+
this.resolve_path(expr.id, path, 0, ValueNS, true)
4096+
});
4097+
for depth in 1..max_assoc_types {
4098+
if result.is_some() {
4099+
break;
4100+
}
4101+
self.with_no_errors(|this| {
4102+
result = this.resolve_path(expr.id, path, depth, TypeNS, true);
4103+
});
4104+
}
4105+
if let Some((DefMod(_), _, _)) = result {
4106+
// A module is not a valid type or value.
4107+
result = None;
40894108
}
40904109

40914110
// This is a local path in the value namespace. Walk through
40924111
// scopes looking for it.
4093-
match self.resolve_path(expr.id, path, 0, ValueNS, true) {
4112+
match result {
40944113
// Check if struct variant
4095-
Some((DefVariant(_, _, true), _, _)) => {
4114+
Some((DefVariant(_, _, true), _, 0)) => {
40964115
let path_name = self.path_names_to_string(path, 0);
40974116
self.resolve_error(expr.span,
40984117
&format!("`{}` is a struct variant name, but \
@@ -4110,6 +4129,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
41104129
debug!("(resolving expr) resolved `{}`",
41114130
self.path_names_to_string(path, 0));
41124131

4132+
// Partial resolutions will need the set of traits in scope,
4133+
// so they can be completed during typeck.
4134+
if def.2 != 0 {
4135+
let method_name = path.segments.last().unwrap().identifier.name;
4136+
let traits = self.search_for_traits_containing_method(method_name);
4137+
self.trait_map.insert(expr.id, traits);
4138+
}
4139+
41134140
self.record_def(expr.id, def);
41144141
}
41154142
None => {
@@ -4135,6 +4162,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
41354162

41364163
}
41374164
_ => {
4165+
// Keep reporting some errors even if they're ignored above.
4166+
self.resolve_path(expr.id, path, 0, ValueNS, true);
4167+
41384168
let mut method_scope = false;
41394169
self.value_ribs.iter().rev().all(|rib| {
41404170
method_scope = match rib.kind {

0 commit comments

Comments
 (0)