From 7673d57b1a9951fa63da899adbd88fc2ce209b0b Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 15 Nov 2013 01:19:58 +0900 Subject: [PATCH] Avoid forcing int and float type variables in early vtable resolution --- src/librustc/middle/astencode.rs | 3 ++ src/librustc/middle/trans/common.rs | 3 ++ src/librustc/middle/trans/meth.rs | 3 ++ src/librustc/middle/ty.rs | 29 +++++++++++++++++++ src/librustc/middle/typeck/check/vtable.rs | 21 +++++++++++++- src/librustc/middle/typeck/check/writeback.rs | 5 +++- src/librustc/middle/typeck/mod.rs | 6 ++++ src/test/run-pass/issue-10436.rs | 18 ++++++++++++ 8 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-10436.rs diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 2eb6dcaf49be4..75fdc0f272585 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -691,6 +691,9 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext, }) }) } + typeck::vtable_none => { + fail!("unexpected vtable_none in astencode") + } } }) } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 5395944ce4605..a64af9975bc19 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1227,6 +1227,9 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt, } } } + typeck::vtable_none => { + tcx.sess.bug("unexpected vtable_none in trans"); + } } } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 3c4aeb9e762c0..2af3ae62508e3 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -364,6 +364,9 @@ pub fn trans_monomorphized_callee(bcx: @mut Block, typeck::vtable_param(..) => { fail!("vtable_param left in monomorphized function's vtable substs"); } + typeck::vtable_none => { + fail!("unexpected vtable_none in trans"); + } }; } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index cabe65b097bb6..4d796660cdced 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -335,6 +335,12 @@ struct ctxt_ { // Maps a trait onto a list of impls of that trait. trait_impls: @mut HashMap, + // Traits implemented by all integral types. + int_traits: @mut HashSet, + + // Traits implemented by all floating point types. + float_traits: @mut HashSet, + // Maps a def_id of a type to a list of its inherent impls. // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. @@ -1009,6 +1015,8 @@ pub fn mk_ctxt(s: session::Session, destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), + int_traits: @mut HashSet::new(), + float_traits: @mut HashSet::new(), inherent_impls: @mut HashMap::new(), impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), @@ -4515,8 +4523,22 @@ pub fn populate_implementations_for_trait_if_necessary( return } + let mut int_count = 0; + let mut float_count = 0; + csearch::each_implementation_for_trait(tcx.sess.cstore, trait_id, |implementation_def_id| { + let ty = lookup_item_type(tcx, implementation_def_id).ty; + match get(ty).sty { + ty_int(..) | ty_uint(..) => { + int_count += 1; + } + ty_float(..) => { + float_count += 1; + } + _ => () + } + let implementation = @csearch::get_impl(tcx, implementation_def_id); // Record the trait->implementation mapping. @@ -4534,6 +4556,13 @@ pub fn populate_implementations_for_trait_if_necessary( tcx.impls.insert(implementation_def_id, implementation); }); + if int_count == 10 { + tcx.int_traits.insert(trait_id); + } + if float_count == 2 { + tcx.float_traits.insert(trait_id); + } + tcx.populated_external_traits.insert(trait_id); } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index abdab02dedd7a..721c3702785cb 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -9,6 +9,7 @@ // except according to those terms. +use middle::ty::{FloatVar, IntVar}; use middle::ty::param_ty; use middle::ty; use middle::ty_fold::TypeFolder; @@ -18,7 +19,7 @@ use middle::typeck::infer::fixup_err_to_str; use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; use middle::typeck::infer; use middle::typeck::{CrateCtxt, vtable_origin, vtable_res, vtable_param_res}; -use middle::typeck::{vtable_static, vtable_param, impl_res}; +use middle::typeck::{vtable_static, vtable_param, vtable_none, impl_res}; use middle::typeck::{param_numbered, param_self, param_index}; use middle::subst::Subst; use util::common::indenter; @@ -233,6 +234,24 @@ fn lookup_vtable(vcx: &VtableContext, vcx.infcx.trait_ref_to_str(trait_ref)); let _i = indenter(); + if is_early { + let tcx = vcx.tcx(); + let ty = vcx.infcx.resolve_type_vars_if_possible(ty); + match ty::get(ty).sty { + ty::ty_infer(IntVar(..)) => { + if tcx.int_traits.contains(&trait_ref.def_id) { + return Some(vtable_none); + } + } + ty::ty_infer(FloatVar(..)) => { + if tcx.float_traits.contains(&trait_ref.def_id) { + return Some(vtable_none); + } + } + _ => () + } + } + let ty = match fixup_ty(vcx, location_info, ty, is_early) { Some(ty) => ty, None => { diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index e2da054527c66..31ac1d6445320 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -20,7 +20,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region}; use middle::typeck::infer::resolve_type; use middle::typeck::infer; use middle::typeck::{vtable_res, vtable_origin}; -use middle::typeck::{vtable_static, vtable_param}; +use middle::typeck::{vtable_static, vtable_param, vtable_none}; use middle::typeck::method_map_entry; use middle::typeck::write_substs_to_tcx; use middle::typeck::write_ty_to_tcx; @@ -110,6 +110,9 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: Span, id: ast::NodeId) { &vtable_param(n, b) => { vtable_param(n, b) } + &vtable_none => { + vtable_none + } } } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index ac7e6940b6070..07867ddcc7c08 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -183,6 +183,9 @@ pub enum vtable_origin { and the second is the bound number (identifying baz) */ vtable_param(param_index, uint), + + // For early vtable resolution + vtable_none, } impl Repr for vtable_origin { @@ -199,6 +202,9 @@ impl Repr for vtable_origin { vtable_param(x, y) => { format!("vtable_param({:?}, {:?})", x, y) } + vtable_none => { + ~"vtable_none" + } } } } diff --git a/src/test/run-pass/issue-10436.rs b/src/test/run-pass/issue-10436.rs new file mode 100644 index 0000000000000..dd3cb29c02791 --- /dev/null +++ b/src/test/run-pass/issue-10436.rs @@ -0,0 +1,18 @@ +// Copyright 2013 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. + +fn f(x: T) -> T { + x +} + +fn main() { + let x: uint = f(0); + assert_eq!(x, 0); +}