From 2a1ba2f1ac45f6bf48e55be4db5e8d1965fccaf8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 5 Jan 2015 16:01:04 -0500 Subject: [PATCH] Permit method calls based on where clauses. --- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 37 ++++++++++++++++++-- src/test/run-pass/method-where-clause.rs | 42 +++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/method-where-clause.rs diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 98a826355a7..b1dc033b567 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -22,7 +22,7 @@ use super::TupleArgumentsFlag; use super::write_call; use middle::infer; -use middle::ty::{mod, Ty}; +use middle::ty::{self, Ty}; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index beb51590b41..94e535cf2ef 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -442,7 +442,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_extension_candidates_for_trait(&mut self, trait_def_id: ast::DefId) { - debug!("assemble_extension_candidates_for_trait: trait_def_id={}", + debug!("assemble_extension_candidates_for_trait(trait_def_id={})", trait_def_id.repr(self.tcx())); // Check whether `trait_def_id` defines a method with suitable name: @@ -471,8 +471,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { matching_index); self.assemble_unboxed_closure_candidates(trait_def_id, - method, + method.clone(), matching_index); + + self.assemble_where_clause_candidates(trait_def_id, + method, + matching_index); } fn assemble_extension_candidates_for_trait_impls(&mut self, @@ -599,6 +603,35 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } } + fn assemble_where_clause_candidates(&mut self, + trait_def_id: ast::DefId, + method_ty: Rc>, + method_index: uint) + { + debug!("assemble_where_clause_candidates(trait_def_id={})", + trait_def_id.repr(self.tcx())); + + // Check whether there are any where-clauses pertaining to this trait. + let caller_predicates = + self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec(); + for bound in traits::elaborate_predicates(self.tcx(), caller_predicates) + .filter_map(|p| p.to_opt_poly_trait_ref()) + .filter(|b| b.def_id() == trait_def_id) + { + let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs()); + + debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}", + bound.repr(self.tcx()), + xform_self_ty.repr(self.tcx())); + + self.extension_candidates.push(Candidate { + xform_self_ty: xform_self_ty, + method_ty: method_ty.clone(), + kind: WhereClauseCandidate(bound, method_index) + }); + } + } + /////////////////////////////////////////////////////////////////////////// // THE ACTUAL SEARCH diff --git a/src/test/run-pass/method-where-clause.rs b/src/test/run-pass/method-where-clause.rs new file mode 100644 index 00000000000..4361c22f55a --- /dev/null +++ b/src/test/run-pass/method-where-clause.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we can use method notation to call methods based on a +// where clause type, and not only type parameters. + +trait Foo { + fn foo(&self) -> int; +} + +impl Foo for Option +{ + fn foo(&self) -> int { + self.unwrap_or(22) + } +} + +impl Foo for Option +{ + fn foo(&self) -> int { + self.unwrap_or(22) as int + } +} + +fn check(x: Option) -> (int, int) + where Option : Foo +{ + let y: Option = None; + (x.foo(), y.foo()) +} + +fn main() { + assert_eq!(check(Some(23u)), (23i, 22i)); + assert_eq!(check(Some(23i)), (23i, 22i)); +}