Skip to content

Commit

Permalink
Use partial path resolutions in expressions for UFCS desugaring.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Feb 24, 2015
1 parent 7a3054f commit fe4f9b8
Show file tree
Hide file tree
Showing 10 changed files with 387 additions and 213 deletions.
33 changes: 16 additions & 17 deletions src/librustc/middle/astconv_util.rs
Expand Up @@ -17,37 +17,36 @@
use middle::def;
use middle::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use util::ppaux::Repr;

pub const NO_REGIONS: uint = 1;
pub const NO_TPS: uint = 2;

pub fn check_path_args(tcx: &ty::ctxt,
span: Span,
segments: &[ast::PathSegment],
flags: uint) {
if (flags & NO_TPS) != 0 {
if segments.iter().any(|s| s.parameters.has_types()) {
span_err!(tcx.sess, span, E0109,
"type parameters are not allowed on this type");
pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
for segment in segments {
if (flags & NO_TPS) != 0 {
for typ in segment.parameters.types() {
span_err!(tcx.sess, typ.span, E0109,
"type parameters are not allowed on this type");
break;
}
}
}

if (flags & NO_REGIONS) != 0 {
if segments.iter().any(|s| s.parameters.has_lifetimes()) {
span_err!(tcx.sess, span, E0110,
"lifetime parameters are not allowed on this type");
if (flags & NO_REGIONS) != 0 {
for lifetime in segment.parameters.lifetimes() {
span_err!(tcx.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type");
break;
}
}
}
}

pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
segments: &[ast::PathSegment],
nty: ast::PrimTy)
-> Ty<'tcx> {
check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
match nty {
ast::TyBool => tcx.types.bool,
ast::TyChar => tcx.types.char,
Expand All @@ -69,7 +68,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
Some(&d) => d
};
if let def::DefPrimTy(nty) = def {
Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty))
Some(prim_ty_to_ty(tcx, &path.segments[], nty))
} else {
None
}
Expand Down
38 changes: 34 additions & 4 deletions src/librustc_resolve/lib.rs
Expand Up @@ -3018,7 +3018,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}

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

ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
if let ExprQPath(_) = expr.node {
let max_assoc_types = if let ExprQPath(_) = expr.node {
// Make sure the trait is valid.
let _ = self.resolve_trait_reference(expr.id, path, 1);
1
} else {
path.segments.len()
};

let mut result = self.with_no_errors(|this| {
this.resolve_path(expr.id, path, 0, ValueNS, true)
});
for depth in 1..max_assoc_types {
if result.is_some() {
break;
}
self.with_no_errors(|this| {
result = this.resolve_path(expr.id, path, depth, TypeNS, true);
});
}
if let Some((DefMod(_), _, _)) = result {
// A module is not a valid type or value.
result = None;
}

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

// Partial resolutions will need the set of traits in scope,
// so they can be completed during typeck.
if def.2 != 0 {
let method_name = path.segments.last().unwrap().identifier.name;
let traits = self.search_for_traits_containing_method(method_name);
self.trait_map.insert(expr.id, traits);
}

self.record_def(expr.id, def);
}
None => {
Expand All @@ -4135,6 +4162,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

}
_ => {
// Keep reporting some errors even if they're ignored above.
self.resolve_path(expr.id, path, 0, ValueNS, true);

let mut method_scope = false;
self.value_ribs.iter().rev().all(|rib| {
method_scope = match rib.kind {
Expand Down

0 comments on commit fe4f9b8

Please sign in to comment.