]> git.lizzy.rs Git - rust.git/commitdiff
Fix ICE with relating late bound regions
authorManish Goregaokar <manishsmail@gmail.com>
Sat, 26 Mar 2016 21:14:25 +0000 (02:44 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Sat, 26 Mar 2016 21:16:36 +0000 (02:46 +0530)
src/methods.rs
src/new_without_default.rs
src/utils/mod.rs

index 95bbdd441c964858b74abf1f2701a031360f79ac..81761695eb8aa7ad6a2b287843ecb506f7892eef 100644 (file)
@@ -402,8 +402,8 @@ fn check_item(&mut self, cx: &LateContext, item: &Item) {
                         }
                     }
 
-                    let ret_ty = return_ty(cx.tcx.node_id_to_type(implitem.id));
-                    if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty))) {
+                    let ret_ty = return_ty(cx, implitem.id);
+                    if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) {
                         span_lint(cx,
                                   NEW_RET_NO_SELF,
                                   sig.explicit_self.span,
index d9b11cc49b6f95304e838034a8fb60b1ecc3cca2..395d69138e13756ff26c5480024b63c4eba7b20e 100644 (file)
@@ -52,8 +52,8 @@ fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &h
 
                 if_let_chain!{[
                     self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
-                    let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)),
-                    same_tys(cx, self_ty, ret_ty),
+                    let Some(ret_ty) = return_ty(cx, id),
+                    same_tys(cx, self_ty, ret_ty, id),
                     let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH),
                     !implements_trait(cx, self_ty, default_trait_id, Vec::new())
                 ], {
index e7b2a9d5210f01d1727bd138f608425a5718a3be..09fb1475b0cfecd1413e4a9dbcd74d2880dd813c 100644 (file)
@@ -4,6 +4,7 @@
 use rustc::middle::def_id::DefId;
 use rustc::middle::traits::ProjectionMode;
 use rustc::middle::{cstore, def, infer, ty, traits};
+use rustc::middle::subst::Subst;
 use rustc::session::Session;
 use rustc_front::hir::*;
 use std::borrow::Cow;
@@ -764,8 +765,13 @@ fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> {
 }
 
 /// Convenience function to get the return type of a function or `None` if the function diverges.
-pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> {
-    if let ty::FnConverging(ret_ty) = fun.fn_sig().skip_binder().output {
+pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> {
+    let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item);
+    let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any);
+
+    let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(infcx.tcx, &infcx.parameter_environment.free_substs);
+    let fn_sig = infcx.tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive, &fn_sig);
+    if let ty::FnConverging(ret_ty) = fn_sig.output {
         Some(ret_ty)
     } else {
         None
@@ -775,7 +781,10 @@ pub fn return_ty(fun: ty::Ty) -> Option<ty::Ty> {
 /// Check if two types are the same.
 // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but
 // not for type parameters.
-pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>) -> bool {
-    let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, None, ProjectionMode::Any);
-    infcx.can_equate(&cx.tcx.erase_regions(&a), &cx.tcx.erase_regions(&b)).is_ok()
+pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>, parameter_item: NodeId) -> bool {
+    let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, parameter_item);
+    let infcx = infer::new_infer_ctxt(cx.tcx, &cx.tcx.tables, Some(parameter_env), ProjectionMode::Any);
+    let new_a = a.subst(infcx.tcx, &infcx.parameter_environment.free_substs);
+    let new_b = b.subst(infcx.tcx, &infcx.parameter_environment.free_substs);
+    infcx.can_equate(&new_a, &new_b).is_ok()
 }